2012-05-02 17:35:42 +00:00
|
|
|
<?php
|
2013-10-21 21:09:13 +00:00
|
|
|
|
2012-05-02 17:35:42 +00:00
|
|
|
/**
|
2013-02-14 11:56:23 +00:00
|
|
|
* @group ContentHandler
|
|
|
|
|
* @group Database
|
|
|
|
|
* ^--- important, causes temporary tables to be used instead of the real database
|
|
|
|
|
* @group medium
|
2016-12-08 16:23:46 +00:00
|
|
|
*/
|
2012-05-23 21:09:15 +00:00
|
|
|
class WikiPageTest extends MediaWikiLangTestCase {
|
2012-05-02 17:35:42 +00:00
|
|
|
|
2013-10-21 21:09:13 +00:00
|
|
|
protected $pages_to_delete;
|
2012-05-02 17:35:42 +00:00
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
function __construct( $name = null, array $data = [], $dataName = '' ) {
|
2012-05-02 17:35:42 +00:00
|
|
|
parent::__construct( $name, $data, $dataName );
|
|
|
|
|
|
2013-02-14 11:56:23 +00:00
|
|
|
$this->tablesUsed = array_merge(
|
2012-10-08 15:26:11 +00:00
|
|
|
$this->tablesUsed,
|
2016-02-17 09:09:32 +00:00
|
|
|
[ 'page',
|
2013-02-14 11:56:23 +00:00
|
|
|
'revision',
|
2017-06-06 17:39:14 +00:00
|
|
|
'archive',
|
2013-02-14 11:56:23 +00:00
|
|
|
'text',
|
2012-05-02 17:35:42 +00:00
|
|
|
|
2013-02-14 11:56:23 +00:00
|
|
|
'recentchanges',
|
|
|
|
|
'logging',
|
2012-05-02 17:35:42 +00:00
|
|
|
|
2013-02-14 11:56:23 +00:00
|
|
|
'page_props',
|
|
|
|
|
'pagelinks',
|
|
|
|
|
'categorylinks',
|
|
|
|
|
'langlinks',
|
|
|
|
|
'externallinks',
|
|
|
|
|
'imagelinks',
|
|
|
|
|
'templatelinks',
|
2016-02-17 09:09:32 +00:00
|
|
|
'iwlinks' ] );
|
2012-05-02 17:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
2012-10-08 10:56:20 +00:00
|
|
|
protected function setUp() {
|
2012-05-23 21:09:15 +00:00
|
|
|
parent::setUp();
|
2016-02-17 09:09:32 +00:00
|
|
|
$this->pages_to_delete = [];
|
2012-05-23 06:53:01 +00:00
|
|
|
|
|
|
|
|
LinkCache::singleton()->clear(); # avoid cached redirect status, etc
|
2012-05-02 17:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
2012-10-08 10:56:20 +00:00
|
|
|
protected function tearDown() {
|
2012-05-02 17:35:42 +00:00
|
|
|
foreach ( $this->pages_to_delete as $p ) {
|
|
|
|
|
/* @var $p WikiPage */
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
if ( $p->exists() ) {
|
|
|
|
|
$p->doDeleteArticle( "testing done." );
|
|
|
|
|
}
|
|
|
|
|
} catch ( MWException $ex ) {
|
|
|
|
|
// fail silently
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-05-23 21:09:15 +00:00
|
|
|
parent::tearDown();
|
2012-05-02 17:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
2012-05-23 06:53:01 +00:00
|
|
|
/**
|
2014-10-31 10:44:16 +00:00
|
|
|
* @param Title|string $title
|
|
|
|
|
* @param string|null $model
|
2012-05-23 06:53:01 +00:00
|
|
|
* @return WikiPage
|
|
|
|
|
*/
|
2012-09-19 18:07:56 +00:00
|
|
|
protected function newPage( $title, $model = null ) {
|
|
|
|
|
if ( is_string( $title ) ) {
|
2012-11-01 12:48:18 +00:00
|
|
|
$ns = $this->getDefaultWikitextNS();
|
|
|
|
|
$title = Title::newFromText( $title, $ns );
|
2012-09-19 18:07:56 +00:00
|
|
|
}
|
2012-05-02 17:35:42 +00:00
|
|
|
|
|
|
|
|
$p = new WikiPage( $title );
|
|
|
|
|
|
|
|
|
|
$this->pages_to_delete[] = $p;
|
|
|
|
|
|
|
|
|
|
return $p;
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-23 06:53:01 +00:00
|
|
|
/**
|
2014-04-17 18:43:42 +00:00
|
|
|
* @param string|Title|WikiPage $page
|
|
|
|
|
* @param string $text
|
2012-05-23 06:53:01 +00:00
|
|
|
* @param int $model
|
|
|
|
|
*
|
|
|
|
|
* @return WikiPage
|
|
|
|
|
*/
|
2012-05-02 17:35:42 +00:00
|
|
|
protected function createPage( $page, $text, $model = null ) {
|
2012-11-01 12:48:18 +00:00
|
|
|
if ( is_string( $page ) || $page instanceof Title ) {
|
2012-09-19 18:07:56 +00:00
|
|
|
$page = $this->newPage( $page, $model );
|
2012-05-23 06:53:01 +00:00
|
|
|
}
|
2012-05-02 17:35:42 +00:00
|
|
|
|
2012-04-24 16:00:21 +00:00
|
|
|
$content = ContentHandler::makeContent( $text, $page->getTitle(), $model );
|
2012-05-02 10:54:27 +00:00
|
|
|
$page->doEditContent( $content, "testing", EDIT_NEW );
|
2012-05-02 17:35:42 +00:00
|
|
|
|
|
|
|
|
return $page;
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-21 21:09:13 +00:00
|
|
|
/**
|
|
|
|
|
* @covers WikiPage::doEditContent
|
2016-10-04 21:06:38 +00:00
|
|
|
* @covers WikiPage::doModify
|
|
|
|
|
* @covers WikiPage::doCreate
|
|
|
|
|
* @covers WikiPage::doEditUpdates
|
2013-10-21 21:09:13 +00:00
|
|
|
*/
|
2012-04-24 16:00:21 +00:00
|
|
|
public function testDoEditContent() {
|
2012-11-01 12:48:18 +00:00
|
|
|
$page = $this->newPage( "WikiPageTest_testDoEditContent" );
|
|
|
|
|
$title = $page->getTitle();
|
2012-04-24 16:00:21 +00:00
|
|
|
|
2014-04-24 12:50:36 +00:00
|
|
|
$content = ContentHandler::makeContent(
|
|
|
|
|
"[[Lorem ipsum]] dolor sit amet, consetetur sadipscing elitr, sed diam "
|
2013-02-14 11:56:23 +00:00
|
|
|
. " nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat.",
|
2014-04-24 12:50:36 +00:00
|
|
|
$title,
|
|
|
|
|
CONTENT_MODEL_WIKITEXT
|
|
|
|
|
);
|
2012-04-24 16:00:21 +00:00
|
|
|
|
2012-05-23 06:53:01 +00:00
|
|
|
$page->doEditContent( $content, "[[testing]] 1" );
|
2012-04-24 16:00:21 +00:00
|
|
|
|
2012-05-23 06:53:01 +00:00
|
|
|
$this->assertTrue( $title->getArticleID() > 0, "Title object should have new page id" );
|
|
|
|
|
$this->assertTrue( $page->getId() > 0, "WikiPage should have new page id" );
|
2012-04-24 16:00:21 +00:00
|
|
|
$this->assertTrue( $title->exists(), "Title object should indicate that the page now exists" );
|
|
|
|
|
$this->assertTrue( $page->exists(), "WikiPage object should indicate that the page now exists" );
|
|
|
|
|
|
2012-04-30 13:32:31 +00:00
|
|
|
$id = $page->getId();
|
|
|
|
|
|
2012-05-23 06:53:01 +00:00
|
|
|
# ------------------------
|
2017-08-04 18:53:34 +00:00
|
|
|
$dbr = wfGetDB( DB_REPLICA );
|
2016-02-17 09:09:32 +00:00
|
|
|
$res = $dbr->select( 'pagelinks', '*', [ 'pl_from' => $id ] );
|
2012-05-23 06:53:01 +00:00
|
|
|
$n = $res->numRows();
|
|
|
|
|
$res->free();
|
|
|
|
|
|
|
|
|
|
$this->assertEquals( 1, $n, 'pagelinks should contain one link from the page' );
|
|
|
|
|
|
2012-04-24 16:00:21 +00:00
|
|
|
# ------------------------
|
|
|
|
|
$page = new WikiPage( $title );
|
|
|
|
|
|
|
|
|
|
$retrieved = $page->getContent();
|
|
|
|
|
$this->assertTrue( $content->equals( $retrieved ), 'retrieved content doesn\'t equal original' );
|
|
|
|
|
|
|
|
|
|
# ------------------------
|
2014-04-24 12:50:36 +00:00
|
|
|
$content = ContentHandler::makeContent(
|
|
|
|
|
"At vero eos et accusam et justo duo [[dolores]] et ea rebum. "
|
2013-02-14 11:56:23 +00:00
|
|
|
. "Stet clita kasd [[gubergren]], no sea takimata sanctus est.",
|
2014-04-24 12:50:36 +00:00
|
|
|
$title,
|
|
|
|
|
CONTENT_MODEL_WIKITEXT
|
|
|
|
|
);
|
2012-04-24 16:00:21 +00:00
|
|
|
|
|
|
|
|
$page->doEditContent( $content, "testing 2" );
|
|
|
|
|
|
|
|
|
|
# ------------------------
|
|
|
|
|
$page = new WikiPage( $title );
|
|
|
|
|
|
|
|
|
|
$retrieved = $page->getContent();
|
|
|
|
|
$this->assertTrue( $content->equals( $retrieved ), 'retrieved content doesn\'t equal original' );
|
2012-04-30 13:32:31 +00:00
|
|
|
|
|
|
|
|
# ------------------------
|
2017-08-04 18:53:34 +00:00
|
|
|
$dbr = wfGetDB( DB_REPLICA );
|
2016-02-17 09:09:32 +00:00
|
|
|
$res = $dbr->select( 'pagelinks', '*', [ 'pl_from' => $id ] );
|
2012-04-30 13:32:31 +00:00
|
|
|
$n = $res->numRows();
|
|
|
|
|
$res->free();
|
|
|
|
|
|
|
|
|
|
$this->assertEquals( 2, $n, 'pagelinks should contain two links from the page' );
|
2012-04-24 16:00:21 +00:00
|
|
|
}
|
2012-09-19 18:07:56 +00:00
|
|
|
|
2013-10-21 21:09:13 +00:00
|
|
|
/**
|
|
|
|
|
* @covers WikiPage::doDeleteArticle
|
|
|
|
|
*/
|
2012-05-02 17:35:42 +00:00
|
|
|
public function testDoDeleteArticle() {
|
2014-04-24 12:50:36 +00:00
|
|
|
$page = $this->createPage(
|
|
|
|
|
"WikiPageTest_testDoDeleteArticle",
|
|
|
|
|
"[[original text]] foo",
|
|
|
|
|
CONTENT_MODEL_WIKITEXT
|
|
|
|
|
);
|
2012-05-02 17:35:42 +00:00
|
|
|
$id = $page->getId();
|
|
|
|
|
|
|
|
|
|
$page->doDeleteArticle( "testing deletion" );
|
|
|
|
|
|
2014-04-24 12:50:36 +00:00
|
|
|
$this->assertFalse(
|
|
|
|
|
$page->getTitle()->getArticleID() > 0,
|
|
|
|
|
"Title object should now have page id 0"
|
|
|
|
|
);
|
2012-05-23 06:53:01 +00:00
|
|
|
$this->assertFalse( $page->getId() > 0, "WikiPage should now have page id 0" );
|
2014-04-24 12:50:36 +00:00
|
|
|
$this->assertFalse(
|
|
|
|
|
$page->exists(),
|
|
|
|
|
"WikiPage::exists should return false after page was deleted"
|
|
|
|
|
);
|
|
|
|
|
$this->assertNull(
|
|
|
|
|
$page->getContent(),
|
|
|
|
|
"WikiPage::getContent should return null after page was deleted"
|
|
|
|
|
);
|
2012-05-02 17:35:42 +00:00
|
|
|
|
|
|
|
|
$t = Title::newFromText( $page->getTitle()->getPrefixedText() );
|
2014-04-24 12:50:36 +00:00
|
|
|
$this->assertFalse(
|
|
|
|
|
$t->exists(),
|
|
|
|
|
"Title::exists should return false after page was deleted"
|
|
|
|
|
);
|
2012-05-02 17:35:42 +00:00
|
|
|
|
2015-09-22 19:07:05 +00:00
|
|
|
// Run the job queue
|
|
|
|
|
JobQueueGroup::destroySingletons();
|
|
|
|
|
$jobs = new RunJobs;
|
2016-02-17 09:09:32 +00:00
|
|
|
$jobs->loadParamsAndArgs( null, [ 'quiet' => true ], null );
|
2015-09-22 19:07:05 +00:00
|
|
|
$jobs->execute();
|
|
|
|
|
|
2012-05-02 17:35:42 +00:00
|
|
|
# ------------------------
|
2017-08-04 18:53:34 +00:00
|
|
|
$dbr = wfGetDB( DB_REPLICA );
|
2016-02-17 09:09:32 +00:00
|
|
|
$res = $dbr->select( 'pagelinks', '*', [ 'pl_from' => $id ] );
|
2012-05-02 17:35:42 +00:00
|
|
|
$n = $res->numRows();
|
|
|
|
|
$res->free();
|
|
|
|
|
|
|
|
|
|
$this->assertEquals( 0, $n, 'pagelinks should contain no more links from the page' );
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-21 21:09:13 +00:00
|
|
|
/**
|
|
|
|
|
* @covers WikiPage::doDeleteUpdates
|
|
|
|
|
*/
|
2012-05-18 16:58:21 +00:00
|
|
|
public function testDoDeleteUpdates() {
|
2014-04-24 12:50:36 +00:00
|
|
|
$page = $this->createPage(
|
|
|
|
|
"WikiPageTest_testDoDeleteArticle",
|
|
|
|
|
"[[original text]] foo",
|
|
|
|
|
CONTENT_MODEL_WIKITEXT
|
|
|
|
|
);
|
2012-05-18 16:58:21 +00:00
|
|
|
$id = $page->getId();
|
|
|
|
|
|
2015-09-22 19:07:05 +00:00
|
|
|
// Similar to MovePage logic
|
2016-02-17 09:09:32 +00:00
|
|
|
wfGetDB( DB_MASTER )->delete( 'page', [ 'page_id' => $id ], __METHOD__ );
|
2012-05-18 16:58:21 +00:00
|
|
|
$page->doDeleteUpdates( $id );
|
|
|
|
|
|
2015-09-22 19:07:05 +00:00
|
|
|
// Run the job queue
|
|
|
|
|
JobQueueGroup::destroySingletons();
|
|
|
|
|
$jobs = new RunJobs;
|
2016-02-17 09:09:32 +00:00
|
|
|
$jobs->loadParamsAndArgs( null, [ 'quiet' => true ], null );
|
2015-09-22 19:07:05 +00:00
|
|
|
$jobs->execute();
|
|
|
|
|
|
2012-05-18 16:58:21 +00:00
|
|
|
# ------------------------
|
2017-08-04 18:53:34 +00:00
|
|
|
$dbr = wfGetDB( DB_REPLICA );
|
2016-02-17 09:09:32 +00:00
|
|
|
$res = $dbr->select( 'pagelinks', '*', [ 'pl_from' => $id ] );
|
2012-05-18 16:58:21 +00:00
|
|
|
$n = $res->numRows();
|
|
|
|
|
$res->free();
|
|
|
|
|
|
|
|
|
|
$this->assertEquals( 0, $n, 'pagelinks should contain no more links from the page' );
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-21 21:09:13 +00:00
|
|
|
/**
|
|
|
|
|
* @covers WikiPage::getRevision
|
|
|
|
|
*/
|
2012-05-02 17:35:42 +00:00
|
|
|
public function testGetRevision() {
|
|
|
|
|
$page = $this->newPage( "WikiPageTest_testGetRevision" );
|
|
|
|
|
|
|
|
|
|
$rev = $page->getRevision();
|
|
|
|
|
$this->assertNull( $rev );
|
|
|
|
|
|
|
|
|
|
# -----------------
|
2012-09-19 18:07:56 +00:00
|
|
|
$this->createPage( $page, "some text", CONTENT_MODEL_WIKITEXT );
|
2012-05-02 17:35:42 +00:00
|
|
|
|
|
|
|
|
$rev = $page->getRevision();
|
|
|
|
|
|
|
|
|
|
$this->assertEquals( $page->getLatest(), $rev->getId() );
|
2012-04-24 16:00:21 +00:00
|
|
|
$this->assertEquals( "some text", $rev->getContent()->getNativeData() );
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-21 21:09:13 +00:00
|
|
|
/**
|
|
|
|
|
* @covers WikiPage::getContent
|
|
|
|
|
*/
|
2012-04-24 16:00:21 +00:00
|
|
|
public function testGetContent() {
|
|
|
|
|
$page = $this->newPage( "WikiPageTest_testGetContent" );
|
|
|
|
|
|
|
|
|
|
$content = $page->getContent();
|
|
|
|
|
$this->assertNull( $content );
|
|
|
|
|
|
|
|
|
|
# -----------------
|
2012-09-19 18:07:56 +00:00
|
|
|
$this->createPage( $page, "some text", CONTENT_MODEL_WIKITEXT );
|
2012-04-24 16:00:21 +00:00
|
|
|
|
|
|
|
|
$content = $page->getContent();
|
|
|
|
|
$this->assertEquals( "some text", $content->getNativeData() );
|
2012-05-02 17:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
2013-10-21 21:09:13 +00:00
|
|
|
/**
|
|
|
|
|
* @covers WikiPage::getContentModel
|
|
|
|
|
*/
|
2012-05-13 22:02:29 +00:00
|
|
|
public function testGetContentModel() {
|
2012-07-24 15:58:02 +00:00
|
|
|
global $wgContentHandlerUseDB;
|
|
|
|
|
|
|
|
|
|
if ( !$wgContentHandlerUseDB ) {
|
|
|
|
|
$this->markTestSkipped( '$wgContentHandlerUseDB is disabled' );
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-24 12:50:36 +00:00
|
|
|
$page = $this->createPage(
|
|
|
|
|
"WikiPageTest_testGetContentModel",
|
|
|
|
|
"some text",
|
|
|
|
|
CONTENT_MODEL_JAVASCRIPT
|
|
|
|
|
);
|
2012-04-24 16:00:21 +00:00
|
|
|
|
|
|
|
|
$page = new WikiPage( $page->getTitle() );
|
2012-05-13 22:02:29 +00:00
|
|
|
$this->assertEquals( CONTENT_MODEL_JAVASCRIPT, $page->getContentModel() );
|
2012-04-24 16:00:21 +00:00
|
|
|
}
|
|
|
|
|
|
2013-10-21 21:09:13 +00:00
|
|
|
/**
|
|
|
|
|
* @covers WikiPage::getContentHandler
|
|
|
|
|
*/
|
2012-04-24 16:00:21 +00:00
|
|
|
public function testGetContentHandler() {
|
2012-07-24 15:58:02 +00:00
|
|
|
global $wgContentHandlerUseDB;
|
|
|
|
|
|
|
|
|
|
if ( !$wgContentHandlerUseDB ) {
|
|
|
|
|
$this->markTestSkipped( '$wgContentHandlerUseDB is disabled' );
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-24 12:50:36 +00:00
|
|
|
$page = $this->createPage(
|
|
|
|
|
"WikiPageTest_testGetContentHandler",
|
|
|
|
|
"some text",
|
|
|
|
|
CONTENT_MODEL_JAVASCRIPT
|
|
|
|
|
);
|
2012-04-24 16:00:21 +00:00
|
|
|
|
|
|
|
|
$page = new WikiPage( $page->getTitle() );
|
|
|
|
|
$this->assertEquals( 'JavaScriptContentHandler', get_class( $page->getContentHandler() ) );
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-21 21:09:13 +00:00
|
|
|
/**
|
|
|
|
|
* @covers WikiPage::exists
|
|
|
|
|
*/
|
2012-05-02 17:35:42 +00:00
|
|
|
public function testExists() {
|
|
|
|
|
$page = $this->newPage( "WikiPageTest_testExists" );
|
|
|
|
|
$this->assertFalse( $page->exists() );
|
|
|
|
|
|
|
|
|
|
# -----------------
|
2012-09-19 18:07:56 +00:00
|
|
|
$this->createPage( $page, "some text", CONTENT_MODEL_WIKITEXT );
|
2012-05-02 17:35:42 +00:00
|
|
|
$this->assertTrue( $page->exists() );
|
|
|
|
|
|
|
|
|
|
$page = new WikiPage( $page->getTitle() );
|
|
|
|
|
$this->assertTrue( $page->exists() );
|
|
|
|
|
|
|
|
|
|
# -----------------
|
|
|
|
|
$page->doDeleteArticle( "done testing" );
|
|
|
|
|
$this->assertFalse( $page->exists() );
|
|
|
|
|
|
|
|
|
|
$page = new WikiPage( $page->getTitle() );
|
|
|
|
|
$this->assertFalse( $page->exists() );
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-08 10:56:20 +00:00
|
|
|
public static function provideHasViewableContent() {
|
2016-02-17 09:09:32 +00:00
|
|
|
return [
|
|
|
|
|
[ 'WikiPageTest_testHasViewableContent', false, true ],
|
|
|
|
|
[ 'Special:WikiPageTest_testHasViewableContent', false ],
|
|
|
|
|
[ 'MediaWiki:WikiPageTest_testHasViewableContent', false ],
|
|
|
|
|
[ 'Special:Userlogin', true ],
|
|
|
|
|
[ 'MediaWiki:help', true ],
|
|
|
|
|
];
|
2012-05-02 17:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2012-10-08 10:56:20 +00:00
|
|
|
* @dataProvider provideHasViewableContent
|
2013-10-21 21:09:13 +00:00
|
|
|
* @covers WikiPage::hasViewableContent
|
2012-05-02 17:35:42 +00:00
|
|
|
*/
|
|
|
|
|
public function testHasViewableContent( $title, $viewable, $create = false ) {
|
|
|
|
|
$page = $this->newPage( $title );
|
|
|
|
|
$this->assertEquals( $viewable, $page->hasViewableContent() );
|
|
|
|
|
|
|
|
|
|
if ( $create ) {
|
2012-09-19 18:07:56 +00:00
|
|
|
$this->createPage( $page, "some text", CONTENT_MODEL_WIKITEXT );
|
2012-05-02 17:35:42 +00:00
|
|
|
$this->assertTrue( $page->hasViewableContent() );
|
|
|
|
|
|
|
|
|
|
$page = new WikiPage( $page->getTitle() );
|
|
|
|
|
$this->assertTrue( $page->hasViewableContent() );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-08 10:56:20 +00:00
|
|
|
public static function provideGetRedirectTarget() {
|
2016-02-17 09:09:32 +00:00
|
|
|
return [
|
|
|
|
|
[ 'WikiPageTest_testGetRedirectTarget_1', CONTENT_MODEL_WIKITEXT, "hello world", null ],
|
|
|
|
|
[
|
2014-04-24 12:50:36 +00:00
|
|
|
'WikiPageTest_testGetRedirectTarget_2',
|
|
|
|
|
CONTENT_MODEL_WIKITEXT,
|
|
|
|
|
"#REDIRECT [[hello world]]",
|
|
|
|
|
"Hello world"
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
];
|
2012-05-02 17:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2012-10-08 10:56:20 +00:00
|
|
|
* @dataProvider provideGetRedirectTarget
|
2013-10-21 21:09:13 +00:00
|
|
|
* @covers WikiPage::getRedirectTarget
|
2012-05-02 17:35:42 +00:00
|
|
|
*/
|
2012-09-19 18:07:56 +00:00
|
|
|
public function testGetRedirectTarget( $title, $model, $text, $target ) {
|
2016-02-17 09:09:32 +00:00
|
|
|
$this->setMwGlobals( [
|
2014-07-07 23:21:09 +00:00
|
|
|
'wgCapitalLinks' => true,
|
2016-02-17 09:09:32 +00:00
|
|
|
] );
|
2014-07-07 23:21:09 +00:00
|
|
|
|
2012-09-19 18:07:56 +00:00
|
|
|
$page = $this->createPage( $title, $text, $model );
|
2012-04-24 16:00:21 +00:00
|
|
|
|
2012-05-02 10:54:27 +00:00
|
|
|
# sanity check, because this test seems to fail for no reason for some people.
|
|
|
|
|
$c = $page->getContent();
|
|
|
|
|
$this->assertEquals( 'WikitextContent', get_class( $c ) );
|
2012-05-02 17:35:42 +00:00
|
|
|
|
|
|
|
|
# now, test the actual redirect
|
|
|
|
|
$t = $page->getRedirectTarget();
|
|
|
|
|
$this->assertEquals( $target, is_null( $t ) ? null : $t->getPrefixedText() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2012-10-08 10:56:20 +00:00
|
|
|
* @dataProvider provideGetRedirectTarget
|
2013-10-21 21:09:13 +00:00
|
|
|
* @covers WikiPage::isRedirect
|
2012-05-02 17:35:42 +00:00
|
|
|
*/
|
2012-09-19 18:07:56 +00:00
|
|
|
public function testIsRedirect( $title, $model, $text, $target ) {
|
|
|
|
|
$page = $this->createPage( $title, $text, $model );
|
2012-05-02 17:35:42 +00:00
|
|
|
$this->assertEquals( !is_null( $target ), $page->isRedirect() );
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-08 10:56:20 +00:00
|
|
|
public static function provideIsCountable() {
|
2016-02-17 09:09:32 +00:00
|
|
|
return [
|
2012-05-02 17:35:42 +00:00
|
|
|
|
|
|
|
|
// any
|
2016-02-17 09:09:32 +00:00
|
|
|
[ 'WikiPageTest_testIsCountable',
|
2013-02-14 11:56:23 +00:00
|
|
|
CONTENT_MODEL_WIKITEXT,
|
|
|
|
|
'',
|
|
|
|
|
'any',
|
|
|
|
|
true
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[ 'WikiPageTest_testIsCountable',
|
2013-02-14 11:56:23 +00:00
|
|
|
CONTENT_MODEL_WIKITEXT,
|
|
|
|
|
'Foo',
|
|
|
|
|
'any',
|
|
|
|
|
true
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
2012-05-02 17:35:42 +00:00
|
|
|
|
|
|
|
|
// comma
|
2016-02-17 09:09:32 +00:00
|
|
|
[ 'WikiPageTest_testIsCountable',
|
2013-02-14 11:56:23 +00:00
|
|
|
CONTENT_MODEL_WIKITEXT,
|
|
|
|
|
'Foo',
|
|
|
|
|
'comma',
|
|
|
|
|
false
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[ 'WikiPageTest_testIsCountable',
|
2013-02-14 11:56:23 +00:00
|
|
|
CONTENT_MODEL_WIKITEXT,
|
|
|
|
|
'Foo, bar',
|
|
|
|
|
'comma',
|
|
|
|
|
true
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
2012-05-02 17:35:42 +00:00
|
|
|
|
|
|
|
|
// link
|
2016-02-17 09:09:32 +00:00
|
|
|
[ 'WikiPageTest_testIsCountable',
|
2013-02-14 11:56:23 +00:00
|
|
|
CONTENT_MODEL_WIKITEXT,
|
|
|
|
|
'Foo',
|
|
|
|
|
'link',
|
|
|
|
|
false
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[ 'WikiPageTest_testIsCountable',
|
2013-02-14 11:56:23 +00:00
|
|
|
CONTENT_MODEL_WIKITEXT,
|
|
|
|
|
'Foo [[bar]]',
|
|
|
|
|
'link',
|
|
|
|
|
true
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
2012-05-02 17:35:42 +00:00
|
|
|
|
|
|
|
|
// redirects
|
2016-02-17 09:09:32 +00:00
|
|
|
[ 'WikiPageTest_testIsCountable',
|
2013-02-14 11:56:23 +00:00
|
|
|
CONTENT_MODEL_WIKITEXT,
|
|
|
|
|
'#REDIRECT [[bar]]',
|
|
|
|
|
'any',
|
|
|
|
|
false
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[ 'WikiPageTest_testIsCountable',
|
2013-02-14 11:56:23 +00:00
|
|
|
CONTENT_MODEL_WIKITEXT,
|
|
|
|
|
'#REDIRECT [[bar]]',
|
|
|
|
|
'comma',
|
|
|
|
|
false
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[ 'WikiPageTest_testIsCountable',
|
2013-02-14 11:56:23 +00:00
|
|
|
CONTENT_MODEL_WIKITEXT,
|
|
|
|
|
'#REDIRECT [[bar]]',
|
|
|
|
|
'link',
|
|
|
|
|
false
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
2012-05-02 17:35:42 +00:00
|
|
|
|
|
|
|
|
// not a content namespace
|
2016-02-17 09:09:32 +00:00
|
|
|
[ 'Talk:WikiPageTest_testIsCountable',
|
2013-02-14 11:56:23 +00:00
|
|
|
CONTENT_MODEL_WIKITEXT,
|
|
|
|
|
'Foo',
|
|
|
|
|
'any',
|
|
|
|
|
false
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[ 'Talk:WikiPageTest_testIsCountable',
|
2013-02-14 11:56:23 +00:00
|
|
|
CONTENT_MODEL_WIKITEXT,
|
|
|
|
|
'Foo, bar',
|
|
|
|
|
'comma',
|
|
|
|
|
false
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[ 'Talk:WikiPageTest_testIsCountable',
|
2013-02-14 11:56:23 +00:00
|
|
|
CONTENT_MODEL_WIKITEXT,
|
|
|
|
|
'Foo [[bar]]',
|
|
|
|
|
'link',
|
|
|
|
|
false
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
2012-05-02 17:35:42 +00:00
|
|
|
|
|
|
|
|
// not a content namespace, different model
|
2016-02-17 09:09:32 +00:00
|
|
|
[ 'MediaWiki:WikiPageTest_testIsCountable.js',
|
2013-02-14 11:56:23 +00:00
|
|
|
null,
|
|
|
|
|
'Foo',
|
|
|
|
|
'any',
|
|
|
|
|
false
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[ 'MediaWiki:WikiPageTest_testIsCountable.js',
|
2013-02-14 11:56:23 +00:00
|
|
|
null,
|
|
|
|
|
'Foo, bar',
|
|
|
|
|
'comma',
|
|
|
|
|
false
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[ 'MediaWiki:WikiPageTest_testIsCountable.js',
|
2013-02-14 11:56:23 +00:00
|
|
|
null,
|
|
|
|
|
'Foo [[bar]]',
|
|
|
|
|
'link',
|
|
|
|
|
false
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
];
|
2012-05-02 17:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2012-10-08 10:56:20 +00:00
|
|
|
* @dataProvider provideIsCountable
|
2013-10-21 21:09:13 +00:00
|
|
|
* @covers WikiPage::isCountable
|
2012-05-02 17:35:42 +00:00
|
|
|
*/
|
2012-09-19 18:07:56 +00:00
|
|
|
public function testIsCountable( $title, $model, $text, $mode, $expected ) {
|
2012-11-01 12:48:18 +00:00
|
|
|
global $wgContentHandlerUseDB;
|
2012-05-02 17:35:42 +00:00
|
|
|
|
2012-11-01 12:48:18 +00:00
|
|
|
$this->setMwGlobals( 'wgArticleCountMethod', $mode );
|
|
|
|
|
|
|
|
|
|
$title = Title::newFromText( $title );
|
|
|
|
|
|
2014-04-24 12:50:36 +00:00
|
|
|
if ( !$wgContentHandlerUseDB
|
|
|
|
|
&& $model
|
|
|
|
|
&& ContentHandler::getDefaultModelFor( $title ) != $model
|
|
|
|
|
) {
|
2012-11-01 12:48:18 +00:00
|
|
|
$this->markTestSkipped( "Can not use non-default content model $model for "
|
2012-12-08 21:04:50 +00:00
|
|
|
. $title->getPrefixedDBkey() . " with \$wgContentHandlerUseDB disabled." );
|
2012-11-01 12:48:18 +00:00
|
|
|
}
|
2012-05-02 17:35:42 +00:00
|
|
|
|
2012-09-19 18:07:56 +00:00
|
|
|
$page = $this->createPage( $title, $text, $model );
|
2012-05-23 06:53:01 +00:00
|
|
|
|
2012-04-24 16:00:21 +00:00
|
|
|
$editInfo = $page->prepareContentForEdit( $page->getContent() );
|
2012-05-02 17:35:42 +00:00
|
|
|
|
|
|
|
|
$v = $page->isCountable();
|
|
|
|
|
$w = $page->isCountable( $editInfo );
|
2012-05-23 06:53:01 +00:00
|
|
|
|
2014-04-24 12:50:36 +00:00
|
|
|
$this->assertEquals(
|
|
|
|
|
$expected,
|
|
|
|
|
$v,
|
|
|
|
|
"isCountable( null ) returned unexpected value " . var_export( $v, true )
|
|
|
|
|
. " instead of " . var_export( $expected, true )
|
|
|
|
|
. " in mode `$mode` for text \"$text\""
|
|
|
|
|
);
|
2012-05-02 17:35:42 +00:00
|
|
|
|
2014-04-24 12:50:36 +00:00
|
|
|
$this->assertEquals(
|
|
|
|
|
$expected,
|
|
|
|
|
$w,
|
|
|
|
|
"isCountable( \$editInfo ) returned unexpected value " . var_export( $v, true )
|
|
|
|
|
. " instead of " . var_export( $expected, true )
|
|
|
|
|
. " in mode `$mode` for text \"$text\""
|
|
|
|
|
);
|
2012-05-02 17:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
2012-10-08 10:56:20 +00:00
|
|
|
public static function provideGetParserOutput() {
|
2016-02-17 09:09:32 +00:00
|
|
|
return [
|
2017-04-27 16:58:17 +00:00
|
|
|
[
|
|
|
|
|
CONTENT_MODEL_WIKITEXT,
|
|
|
|
|
"hello ''world''\n",
|
|
|
|
|
"<div class=\"mw-parser-output\"><p>hello <i>world</i></p></div>"
|
|
|
|
|
],
|
2013-05-15 01:12:35 +00:00
|
|
|
// @todo more...?
|
2016-02-17 09:09:32 +00:00
|
|
|
];
|
2012-05-02 17:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2012-10-08 10:56:20 +00:00
|
|
|
* @dataProvider provideGetParserOutput
|
2013-10-21 21:09:13 +00:00
|
|
|
* @covers WikiPage::getParserOutput
|
2012-05-02 17:35:42 +00:00
|
|
|
*/
|
2012-09-19 18:07:56 +00:00
|
|
|
public function testGetParserOutput( $model, $text, $expectedHtml ) {
|
|
|
|
|
$page = $this->createPage( 'WikiPageTest_testGetParserOutput', $text, $model );
|
2012-05-02 17:35:42 +00:00
|
|
|
|
2012-10-14 19:34:26 +00:00
|
|
|
$opt = $page->makeParserOptions( 'canonical' );
|
2012-05-02 17:35:42 +00:00
|
|
|
$po = $page->getParserOutput( $opt );
|
|
|
|
|
$text = $po->getText();
|
|
|
|
|
|
|
|
|
|
$text = trim( preg_replace( '/<!--.*?-->/sm', '', $text ) ); # strip injected comments
|
2017-04-27 16:58:17 +00:00
|
|
|
$text = preg_replace( '!\s*(</p>|</div>)!sm', '\1', $text ); # don't let tidy confuse us
|
2012-05-02 17:35:42 +00:00
|
|
|
|
|
|
|
|
$this->assertEquals( $expectedHtml, $text );
|
2013-04-26 12:00:22 +00:00
|
|
|
|
2012-05-02 17:35:42 +00:00
|
|
|
return $po;
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-21 21:09:13 +00:00
|
|
|
/**
|
|
|
|
|
* @covers WikiPage::getParserOutput
|
|
|
|
|
*/
|
2013-02-14 11:56:23 +00:00
|
|
|
public function testGetParserOutput_nonexisting() {
|
2012-10-15 12:36:03 +00:00
|
|
|
static $count = 0;
|
2013-02-14 11:56:23 +00:00
|
|
|
$count++;
|
2012-10-15 12:36:03 +00:00
|
|
|
|
2012-10-18 12:44:47 +00:00
|
|
|
$page = new WikiPage( new Title( "WikiPageTest_testGetParserOutput_nonexisting_$count" ) );
|
2012-10-15 12:36:03 +00:00
|
|
|
|
|
|
|
|
$opt = new ParserOptions();
|
|
|
|
|
$po = $page->getParserOutput( $opt );
|
|
|
|
|
|
|
|
|
|
$this->assertFalse( $po, "getParserOutput() shall return false for non-existing pages." );
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-21 21:09:13 +00:00
|
|
|
/**
|
|
|
|
|
* @covers WikiPage::getParserOutput
|
|
|
|
|
*/
|
2013-02-14 11:56:23 +00:00
|
|
|
public function testGetParserOutput_badrev() {
|
2012-10-18 12:44:47 +00:00
|
|
|
$page = $this->createPage( 'WikiPageTest_testGetParserOutput', "dummy", CONTENT_MODEL_WIKITEXT );
|
|
|
|
|
|
|
|
|
|
$opt = new ParserOptions();
|
|
|
|
|
$po = $page->getParserOutput( $opt, $page->getLatest() + 1234 );
|
|
|
|
|
|
2013-05-15 01:12:35 +00:00
|
|
|
// @todo would be neat to also test deleted revision
|
2012-10-18 12:44:47 +00:00
|
|
|
|
|
|
|
|
$this->assertFalse( $po, "getParserOutput() shall return false for non-existing revisions." );
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-24 12:50:36 +00:00
|
|
|
public static $sections =
|
2012-05-02 17:35:42 +00:00
|
|
|
|
|
|
|
|
"Intro
|
|
|
|
|
|
|
|
|
|
== stuff ==
|
|
|
|
|
hello world
|
|
|
|
|
|
|
|
|
|
== test ==
|
|
|
|
|
just a test
|
|
|
|
|
|
|
|
|
|
== foo ==
|
|
|
|
|
more stuff
|
|
|
|
|
";
|
|
|
|
|
|
2012-04-24 16:00:21 +00:00
|
|
|
public function dataReplaceSection() {
|
2015-09-11 13:44:59 +00:00
|
|
|
// NOTE: assume the Help namespace to contain wikitext
|
2016-02-17 09:09:32 +00:00
|
|
|
return [
|
|
|
|
|
[ 'Help:WikiPageTest_testReplaceSection',
|
2013-02-14 11:56:23 +00:00
|
|
|
CONTENT_MODEL_WIKITEXT,
|
2017-07-23 01:24:09 +00:00
|
|
|
self::$sections,
|
2013-02-14 11:56:23 +00:00
|
|
|
"0",
|
|
|
|
|
"No more",
|
|
|
|
|
null,
|
2017-07-23 01:24:09 +00:00
|
|
|
trim( preg_replace( '/^Intro/sm', 'No more', self::$sections ) )
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[ 'Help:WikiPageTest_testReplaceSection',
|
2013-02-14 11:56:23 +00:00
|
|
|
CONTENT_MODEL_WIKITEXT,
|
2017-07-23 01:24:09 +00:00
|
|
|
self::$sections,
|
2013-02-14 11:56:23 +00:00
|
|
|
"",
|
|
|
|
|
"No more",
|
|
|
|
|
null,
|
|
|
|
|
"No more"
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[ 'Help:WikiPageTest_testReplaceSection',
|
2013-02-14 11:56:23 +00:00
|
|
|
CONTENT_MODEL_WIKITEXT,
|
2017-07-23 01:24:09 +00:00
|
|
|
self::$sections,
|
2013-02-14 11:56:23 +00:00
|
|
|
"2",
|
|
|
|
|
"== TEST ==\nmore fun",
|
|
|
|
|
null,
|
|
|
|
|
trim( preg_replace( '/^== test ==.*== foo ==/sm',
|
|
|
|
|
"== TEST ==\nmore fun\n\n== foo ==",
|
2017-07-23 01:24:09 +00:00
|
|
|
self::$sections ) )
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[ 'Help:WikiPageTest_testReplaceSection',
|
2013-02-14 11:56:23 +00:00
|
|
|
CONTENT_MODEL_WIKITEXT,
|
2017-07-23 01:24:09 +00:00
|
|
|
self::$sections,
|
2013-02-14 11:56:23 +00:00
|
|
|
"8",
|
|
|
|
|
"No more",
|
|
|
|
|
null,
|
2017-07-23 01:24:09 +00:00
|
|
|
trim( self::$sections )
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[ 'Help:WikiPageTest_testReplaceSection',
|
2013-02-14 11:56:23 +00:00
|
|
|
CONTENT_MODEL_WIKITEXT,
|
2017-07-23 01:24:09 +00:00
|
|
|
self::$sections,
|
2013-02-14 11:56:23 +00:00
|
|
|
"new",
|
|
|
|
|
"No more",
|
|
|
|
|
"New",
|
2017-07-23 01:24:09 +00:00
|
|
|
trim( self::$sections ) . "\n\n== New ==\n\nNo more"
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
];
|
2012-05-02 17:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
2012-04-24 16:00:21 +00:00
|
|
|
/**
|
|
|
|
|
* @dataProvider dataReplaceSection
|
2013-10-21 21:09:13 +00:00
|
|
|
* @covers WikiPage::replaceSectionContent
|
2012-04-24 16:00:21 +00:00
|
|
|
*/
|
2014-04-24 12:50:36 +00:00
|
|
|
public function testReplaceSectionContent( $title, $model, $text, $section,
|
|
|
|
|
$with, $sectionTitle, $expected
|
|
|
|
|
) {
|
2012-09-19 18:07:56 +00:00
|
|
|
$page = $this->createPage( $title, $text, $model );
|
2012-04-24 16:00:21 +00:00
|
|
|
|
2012-05-13 22:02:29 +00:00
|
|
|
$content = ContentHandler::makeContent( $with, $page->getTitle(), $page->getContentModel() );
|
2012-04-24 16:00:21 +00:00
|
|
|
$c = $page->replaceSectionContent( $section, $content, $sectionTitle );
|
|
|
|
|
|
|
|
|
|
$this->assertEquals( $expected, is_null( $c ) ? null : trim( $c->getNativeData() ) );
|
|
|
|
|
}
|
2012-09-19 18:07:56 +00:00
|
|
|
|
2014-05-18 21:26:17 +00:00
|
|
|
/**
|
|
|
|
|
* @dataProvider dataReplaceSection
|
|
|
|
|
* @covers WikiPage::replaceSectionAtRev
|
|
|
|
|
*/
|
|
|
|
|
public function testReplaceSectionAtRev( $title, $model, $text, $section,
|
|
|
|
|
$with, $sectionTitle, $expected
|
|
|
|
|
) {
|
|
|
|
|
$page = $this->createPage( $title, $text, $model );
|
|
|
|
|
$baseRevId = $page->getLatest();
|
|
|
|
|
|
|
|
|
|
$content = ContentHandler::makeContent( $with, $page->getTitle(), $page->getContentModel() );
|
|
|
|
|
$c = $page->replaceSectionAtRev( $section, $content, $sectionTitle, $baseRevId );
|
|
|
|
|
|
|
|
|
|
$this->assertEquals( $expected, is_null( $c ) ? null : trim( $c->getNativeData() ) );
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-10 15:16:46 +00:00
|
|
|
/* @todo FIXME: fix this!
|
2012-05-02 17:35:42 +00:00
|
|
|
public function testGetUndoText() {
|
2016-01-27 18:56:09 +00:00
|
|
|
$this->markTestSkippedIfNoDiff3();
|
2012-05-02 17:35:42 +00:00
|
|
|
|
2013-02-14 11:56:23 +00:00
|
|
|
$text = "one";
|
|
|
|
|
$page = $this->createPage( "WikiPageTest_testGetUndoText", $text );
|
|
|
|
|
$rev1 = $page->getRevision();
|
2012-05-02 17:35:42 +00:00
|
|
|
|
2013-02-14 11:56:23 +00:00
|
|
|
$text .= "\n\ntwo";
|
2014-04-24 12:50:36 +00:00
|
|
|
$page->doEditContent(
|
|
|
|
|
ContentHandler::makeContent( $text, $page->getTitle() ),
|
|
|
|
|
"adding section two"
|
|
|
|
|
);
|
2013-02-14 11:56:23 +00:00
|
|
|
$rev2 = $page->getRevision();
|
2012-05-02 17:35:42 +00:00
|
|
|
|
2013-02-14 11:56:23 +00:00
|
|
|
$text .= "\n\nthree";
|
2014-04-24 12:50:36 +00:00
|
|
|
$page->doEditContent(
|
|
|
|
|
ContentHandler::makeContent( $text, $page->getTitle() ),
|
|
|
|
|
"adding section three"
|
|
|
|
|
);
|
2013-02-14 11:56:23 +00:00
|
|
|
$rev3 = $page->getRevision();
|
2012-05-02 17:35:42 +00:00
|
|
|
|
2013-02-14 11:56:23 +00:00
|
|
|
$text .= "\n\nfour";
|
2014-04-24 12:50:36 +00:00
|
|
|
$page->doEditContent(
|
|
|
|
|
ContentHandler::makeContent( $text, $page->getTitle() ),
|
|
|
|
|
"adding section four"
|
|
|
|
|
);
|
2013-02-14 11:56:23 +00:00
|
|
|
$rev4 = $page->getRevision();
|
2012-05-02 17:35:42 +00:00
|
|
|
|
2013-02-14 11:56:23 +00:00
|
|
|
$text .= "\n\nfive";
|
2014-04-24 12:50:36 +00:00
|
|
|
$page->doEditContent(
|
|
|
|
|
ContentHandler::makeContent( $text, $page->getTitle() ),
|
|
|
|
|
"adding section five"
|
|
|
|
|
);
|
2013-02-14 11:56:23 +00:00
|
|
|
$rev5 = $page->getRevision();
|
2012-05-02 17:35:42 +00:00
|
|
|
|
2013-02-14 11:56:23 +00:00
|
|
|
$text .= "\n\nsix";
|
2014-04-24 12:50:36 +00:00
|
|
|
$page->doEditContent(
|
|
|
|
|
ContentHandler::makeContent( $text, $page->getTitle() ),
|
|
|
|
|
"adding section six"
|
|
|
|
|
);
|
2013-02-14 11:56:23 +00:00
|
|
|
$rev6 = $page->getRevision();
|
2012-05-02 17:35:42 +00:00
|
|
|
|
2013-02-14 11:56:23 +00:00
|
|
|
$undo6 = $page->getUndoText( $rev6 );
|
|
|
|
|
if ( $undo6 === false ) $this->fail( "getUndoText failed for rev6" );
|
|
|
|
|
$this->assertEquals( "one\n\ntwo\n\nthree\n\nfour\n\nfive", $undo6 );
|
2012-05-02 17:35:42 +00:00
|
|
|
|
2013-02-14 11:56:23 +00:00
|
|
|
$undo3 = $page->getUndoText( $rev4, $rev2 );
|
|
|
|
|
if ( $undo3 === false ) $this->fail( "getUndoText failed for rev4..rev2" );
|
|
|
|
|
$this->assertEquals( "one\n\ntwo\n\nfive", $undo3 );
|
2012-05-02 17:35:42 +00:00
|
|
|
|
2013-02-14 11:56:23 +00:00
|
|
|
$undo2 = $page->getUndoText( $rev2 );
|
|
|
|
|
if ( $undo2 === false ) $this->fail( "getUndoText failed for rev2" );
|
|
|
|
|
$this->assertEquals( "one\n\nfive", $undo2 );
|
2012-05-02 17:35:42 +00:00
|
|
|
}
|
2013-02-14 11:56:23 +00:00
|
|
|
*/
|
2012-05-02 17:35:42 +00:00
|
|
|
|
2017-02-01 11:47:20 +00:00
|
|
|
/**
|
|
|
|
|
* @covers WikiPage::getOldestRevision
|
|
|
|
|
*/
|
|
|
|
|
public function testGetOldestRevision() {
|
|
|
|
|
$page = $this->newPage( "WikiPageTest_testGetOldestRevision" );
|
|
|
|
|
$page->doEditContent(
|
|
|
|
|
new WikitextContent( 'one' ),
|
|
|
|
|
"first edit",
|
|
|
|
|
EDIT_NEW
|
|
|
|
|
);
|
|
|
|
|
$rev1 = $page->getRevision();
|
|
|
|
|
|
|
|
|
|
$page = new WikiPage( $page->getTitle() );
|
|
|
|
|
$page->doEditContent(
|
|
|
|
|
new WikitextContent( 'two' ),
|
|
|
|
|
"second edit",
|
|
|
|
|
EDIT_UPDATE
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$page = new WikiPage( $page->getTitle() );
|
|
|
|
|
$page->doEditContent(
|
|
|
|
|
new WikitextContent( 'three' ),
|
|
|
|
|
"third edit",
|
|
|
|
|
EDIT_UPDATE
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// sanity check
|
|
|
|
|
$this->assertNotEquals(
|
|
|
|
|
$rev1->getId(),
|
|
|
|
|
$page->getRevision()->getId(),
|
|
|
|
|
'$page->getRevision()->getId()'
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// actual test
|
|
|
|
|
$this->assertEquals(
|
|
|
|
|
$rev1->getId(),
|
|
|
|
|
$page->getOldestRevision()->getId(),
|
|
|
|
|
'$page->getOldestRevision()->getId()'
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-02 17:35:42 +00:00
|
|
|
/**
|
2014-04-24 12:50:36 +00:00
|
|
|
* @todo FIXME: this is a better rollback test than the one below, but it
|
|
|
|
|
* keeps failing in jenkins for some reason.
|
2012-05-02 17:35:42 +00:00
|
|
|
*/
|
|
|
|
|
public function broken_testDoRollback() {
|
|
|
|
|
$admin = new User();
|
2013-02-14 11:56:23 +00:00
|
|
|
$admin->setName( "Admin" );
|
2012-05-02 17:35:42 +00:00
|
|
|
|
|
|
|
|
$text = "one";
|
|
|
|
|
$page = $this->newPage( "WikiPageTest_testDoRollback" );
|
2012-08-20 19:33:07 +00:00
|
|
|
$page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ),
|
2013-02-14 11:56:23 +00:00
|
|
|
"section one", EDIT_NEW, false, $admin );
|
2012-05-02 17:35:42 +00:00
|
|
|
|
|
|
|
|
$user1 = new User();
|
|
|
|
|
$user1->setName( "127.0.1.11" );
|
|
|
|
|
$text .= "\n\ntwo";
|
|
|
|
|
$page = new WikiPage( $page->getTitle() );
|
2012-08-20 19:33:07 +00:00
|
|
|
$page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ),
|
2013-02-14 11:56:23 +00:00
|
|
|
"adding section two", 0, false, $user1 );
|
2012-05-02 17:35:42 +00:00
|
|
|
|
|
|
|
|
$user2 = new User();
|
|
|
|
|
$user2->setName( "127.0.2.13" );
|
|
|
|
|
$text .= "\n\nthree";
|
|
|
|
|
$page = new WikiPage( $page->getTitle() );
|
2012-08-20 19:33:07 +00:00
|
|
|
$page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ),
|
2013-02-14 11:56:23 +00:00
|
|
|
"adding section three", 0, false, $user2 );
|
2012-05-02 17:35:42 +00:00
|
|
|
|
2014-04-24 12:50:36 +00:00
|
|
|
# we are having issues with doRollback spuriously failing. Apparently
|
|
|
|
|
# the last revision somehow goes missing or not committed under some
|
|
|
|
|
# circumstances. So, make sure the last revision has the right user name.
|
2017-08-04 18:53:34 +00:00
|
|
|
$dbr = wfGetDB( DB_REPLICA );
|
2012-05-02 17:35:42 +00:00
|
|
|
$this->assertEquals( 3, Revision::countByPageId( $dbr, $page->getId() ) );
|
|
|
|
|
|
|
|
|
|
$page = new WikiPage( $page->getTitle() );
|
|
|
|
|
$rev3 = $page->getRevision();
|
|
|
|
|
$this->assertEquals( '127.0.2.13', $rev3->getUserText() );
|
|
|
|
|
|
|
|
|
|
$rev2 = $rev3->getPrevious();
|
|
|
|
|
$this->assertEquals( '127.0.1.11', $rev2->getUserText() );
|
|
|
|
|
|
|
|
|
|
$rev1 = $rev2->getPrevious();
|
|
|
|
|
$this->assertEquals( 'Admin', $rev1->getUserText() );
|
|
|
|
|
|
|
|
|
|
# now, try the actual rollback
|
User group memberships that expire
This patch adds an ug_expiry column to the user_groups table, a timestamp
giving a date when the user group expires. A new UserGroupMembership class,
based on the Block class, manages entries in this table.
When the expiry date passes, the row in user_groups is ignored, and will
eventually be purged from the DB when UserGroupMembership::insert is next
called. Old, expired user group memberships are not kept; instead, the log
entries are available to find the history of these memberships, similar
to the way it has always worked for blocks and protections.
Anyone getting user group info through the User object will get correct
information. However, code that reads the user_groups table directly will
now need to skip over rows with ug_expiry < wfTimestampNow(). See
UsersPager for an example of how to do this.
NULL is used to represent infinite (no) expiry, rather than a string
'infinity' or similar (except in the API). This allows existing user group
assignments and log entries, which are all infinite in duration, to be
treated the same as new, infinite-length memberships, without special
casing everything.
The whole thing is behind the temporary feature flag
$wgDisableUserGroupExpiry, in accordance with the WMF schema change policy.
The opportunity has been taken to refactor some static user-group-related
functions out of User into UserGroupMembership, and also to add a primary
key (ug_user, ug_group) to the user_groups table.
There are a few breaking changes:
- UserRightsProxy-like objects are now required to have a
getGroupMemberships() function.
- $user->mGroups (on a User object) is no longer present.
- Some protected functions in UsersPager are altered or removed.
- The UsersPagerDoBatchLookups hook (unused in any Wikimedia Git-hosted
extension) has a change of parameter.
Bug: T12493
Depends-On: Ia9616e1e35184fed9058d2d39afbe1038f56d7fa
Depends-On: I86eb1d5619347ce54a5f33a591417742ebe5d6f8
Change-Id: I93c955dc7a970f78e32aa503c01c67da30971d1a
2017-01-12 06:07:56 +00:00
|
|
|
$admin->addToDatabase();
|
2015-09-11 13:44:59 +00:00
|
|
|
$admin->addGroup( "sysop" ); # XXX: make the test user a sysop...
|
2014-04-24 12:50:36 +00:00
|
|
|
$token = $admin->getEditToken(
|
2016-02-17 09:09:32 +00:00
|
|
|
[ $page->getTitle()->getPrefixedText(), $user2->getName() ],
|
2014-04-24 12:50:36 +00:00
|
|
|
null
|
|
|
|
|
);
|
|
|
|
|
$errors = $page->doRollback(
|
|
|
|
|
$user2->getName(),
|
|
|
|
|
"testing revert",
|
|
|
|
|
$token,
|
|
|
|
|
false,
|
|
|
|
|
$details,
|
|
|
|
|
$admin
|
|
|
|
|
);
|
2012-05-02 17:35:42 +00:00
|
|
|
|
|
|
|
|
if ( $errors ) {
|
2014-04-24 12:50:36 +00:00
|
|
|
$this->fail( "Rollback failed:\n" . print_r( $errors, true )
|
|
|
|
|
. ";\n" . print_r( $details, true ) );
|
2012-05-02 17:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$page = new WikiPage( $page->getTitle() );
|
2012-08-20 19:33:07 +00:00
|
|
|
$this->assertEquals( $rev2->getSha1(), $page->getRevision()->getSha1(),
|
2013-02-14 11:56:23 +00:00
|
|
|
"rollback did not revert to the correct revision" );
|
2012-04-24 16:00:21 +00:00
|
|
|
$this->assertEquals( "one\n\ntwo", $page->getContent()->getNativeData() );
|
2012-05-02 17:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @todo FIXME: the above rollback test is better, but it keeps failing in jenkins for some reason.
|
2013-10-21 21:09:13 +00:00
|
|
|
* @covers WikiPage::doRollback
|
2012-05-02 17:35:42 +00:00
|
|
|
*/
|
|
|
|
|
public function testDoRollback() {
|
|
|
|
|
$admin = new User();
|
2013-02-14 11:56:23 +00:00
|
|
|
$admin->setName( "Admin" );
|
User group memberships that expire
This patch adds an ug_expiry column to the user_groups table, a timestamp
giving a date when the user group expires. A new UserGroupMembership class,
based on the Block class, manages entries in this table.
When the expiry date passes, the row in user_groups is ignored, and will
eventually be purged from the DB when UserGroupMembership::insert is next
called. Old, expired user group memberships are not kept; instead, the log
entries are available to find the history of these memberships, similar
to the way it has always worked for blocks and protections.
Anyone getting user group info through the User object will get correct
information. However, code that reads the user_groups table directly will
now need to skip over rows with ug_expiry < wfTimestampNow(). See
UsersPager for an example of how to do this.
NULL is used to represent infinite (no) expiry, rather than a string
'infinity' or similar (except in the API). This allows existing user group
assignments and log entries, which are all infinite in duration, to be
treated the same as new, infinite-length memberships, without special
casing everything.
The whole thing is behind the temporary feature flag
$wgDisableUserGroupExpiry, in accordance with the WMF schema change policy.
The opportunity has been taken to refactor some static user-group-related
functions out of User into UserGroupMembership, and also to add a primary
key (ug_user, ug_group) to the user_groups table.
There are a few breaking changes:
- UserRightsProxy-like objects are now required to have a
getGroupMemberships() function.
- $user->mGroups (on a User object) is no longer present.
- Some protected functions in UsersPager are altered or removed.
- The UsersPagerDoBatchLookups hook (unused in any Wikimedia Git-hosted
extension) has a change of parameter.
Bug: T12493
Depends-On: Ia9616e1e35184fed9058d2d39afbe1038f56d7fa
Depends-On: I86eb1d5619347ce54a5f33a591417742ebe5d6f8
Change-Id: I93c955dc7a970f78e32aa503c01c67da30971d1a
2017-01-12 06:07:56 +00:00
|
|
|
$admin->addToDatabase();
|
2012-05-02 17:35:42 +00:00
|
|
|
|
|
|
|
|
$text = "one";
|
|
|
|
|
$page = $this->newPage( "WikiPageTest_testDoRollback" );
|
2014-04-24 12:50:36 +00:00
|
|
|
$page->doEditContent(
|
|
|
|
|
ContentHandler::makeContent( $text, $page->getTitle(), CONTENT_MODEL_WIKITEXT ),
|
|
|
|
|
"section one",
|
|
|
|
|
EDIT_NEW,
|
|
|
|
|
false,
|
|
|
|
|
$admin
|
|
|
|
|
);
|
2012-05-02 17:35:42 +00:00
|
|
|
$rev1 = $page->getRevision();
|
|
|
|
|
|
|
|
|
|
$user1 = new User();
|
|
|
|
|
$user1->setName( "127.0.1.11" );
|
|
|
|
|
$text .= "\n\ntwo";
|
|
|
|
|
$page = new WikiPage( $page->getTitle() );
|
2014-04-24 12:50:36 +00:00
|
|
|
$page->doEditContent(
|
|
|
|
|
ContentHandler::makeContent( $text, $page->getTitle(), CONTENT_MODEL_WIKITEXT ),
|
|
|
|
|
"adding section two",
|
|
|
|
|
0,
|
|
|
|
|
false,
|
|
|
|
|
$user1
|
|
|
|
|
);
|
2012-05-02 17:35:42 +00:00
|
|
|
|
|
|
|
|
# now, try the rollback
|
2015-09-11 13:44:59 +00:00
|
|
|
$admin->addGroup( "sysop" ); # XXX: make the test user a sysop...
|
User group memberships that expire
This patch adds an ug_expiry column to the user_groups table, a timestamp
giving a date when the user group expires. A new UserGroupMembership class,
based on the Block class, manages entries in this table.
When the expiry date passes, the row in user_groups is ignored, and will
eventually be purged from the DB when UserGroupMembership::insert is next
called. Old, expired user group memberships are not kept; instead, the log
entries are available to find the history of these memberships, similar
to the way it has always worked for blocks and protections.
Anyone getting user group info through the User object will get correct
information. However, code that reads the user_groups table directly will
now need to skip over rows with ug_expiry < wfTimestampNow(). See
UsersPager for an example of how to do this.
NULL is used to represent infinite (no) expiry, rather than a string
'infinity' or similar (except in the API). This allows existing user group
assignments and log entries, which are all infinite in duration, to be
treated the same as new, infinite-length memberships, without special
casing everything.
The whole thing is behind the temporary feature flag
$wgDisableUserGroupExpiry, in accordance with the WMF schema change policy.
The opportunity has been taken to refactor some static user-group-related
functions out of User into UserGroupMembership, and also to add a primary
key (ug_user, ug_group) to the user_groups table.
There are a few breaking changes:
- UserRightsProxy-like objects are now required to have a
getGroupMemberships() function.
- $user->mGroups (on a User object) is no longer present.
- Some protected functions in UsersPager are altered or removed.
- The UsersPagerDoBatchLookups hook (unused in any Wikimedia Git-hosted
extension) has a change of parameter.
Bug: T12493
Depends-On: Ia9616e1e35184fed9058d2d39afbe1038f56d7fa
Depends-On: I86eb1d5619347ce54a5f33a591417742ebe5d6f8
Change-Id: I93c955dc7a970f78e32aa503c01c67da30971d1a
2017-01-12 06:07:56 +00:00
|
|
|
$token = $admin->getEditToken( 'rollback' );
|
2014-04-24 12:50:36 +00:00
|
|
|
$errors = $page->doRollback(
|
|
|
|
|
$user1->getName(),
|
|
|
|
|
"testing revert",
|
|
|
|
|
$token,
|
|
|
|
|
false,
|
|
|
|
|
$details,
|
|
|
|
|
$admin
|
|
|
|
|
);
|
2012-05-02 17:35:42 +00:00
|
|
|
|
|
|
|
|
if ( $errors ) {
|
2014-04-24 12:50:36 +00:00
|
|
|
$this->fail( "Rollback failed:\n" . print_r( $errors, true )
|
|
|
|
|
. ";\n" . print_r( $details, true ) );
|
2012-05-02 17:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$page = new WikiPage( $page->getTitle() );
|
2012-08-20 19:33:07 +00:00
|
|
|
$this->assertEquals( $rev1->getSha1(), $page->getRevision()->getSha1(),
|
2014-02-17 19:24:13 +00:00
|
|
|
"rollback did not revert to the correct revision" );
|
|
|
|
|
$this->assertEquals( "one", $page->getContent()->getNativeData() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers WikiPage::doRollback
|
|
|
|
|
*/
|
|
|
|
|
public function testDoRollbackFailureSameContent() {
|
|
|
|
|
$admin = new User();
|
|
|
|
|
$admin->setName( "Admin" );
|
User group memberships that expire
This patch adds an ug_expiry column to the user_groups table, a timestamp
giving a date when the user group expires. A new UserGroupMembership class,
based on the Block class, manages entries in this table.
When the expiry date passes, the row in user_groups is ignored, and will
eventually be purged from the DB when UserGroupMembership::insert is next
called. Old, expired user group memberships are not kept; instead, the log
entries are available to find the history of these memberships, similar
to the way it has always worked for blocks and protections.
Anyone getting user group info through the User object will get correct
information. However, code that reads the user_groups table directly will
now need to skip over rows with ug_expiry < wfTimestampNow(). See
UsersPager for an example of how to do this.
NULL is used to represent infinite (no) expiry, rather than a string
'infinity' or similar (except in the API). This allows existing user group
assignments and log entries, which are all infinite in duration, to be
treated the same as new, infinite-length memberships, without special
casing everything.
The whole thing is behind the temporary feature flag
$wgDisableUserGroupExpiry, in accordance with the WMF schema change policy.
The opportunity has been taken to refactor some static user-group-related
functions out of User into UserGroupMembership, and also to add a primary
key (ug_user, ug_group) to the user_groups table.
There are a few breaking changes:
- UserRightsProxy-like objects are now required to have a
getGroupMemberships() function.
- $user->mGroups (on a User object) is no longer present.
- Some protected functions in UsersPager are altered or removed.
- The UsersPagerDoBatchLookups hook (unused in any Wikimedia Git-hosted
extension) has a change of parameter.
Bug: T12493
Depends-On: Ia9616e1e35184fed9058d2d39afbe1038f56d7fa
Depends-On: I86eb1d5619347ce54a5f33a591417742ebe5d6f8
Change-Id: I93c955dc7a970f78e32aa503c01c67da30971d1a
2017-01-12 06:07:56 +00:00
|
|
|
$admin->addToDatabase();
|
2015-09-11 13:44:59 +00:00
|
|
|
$admin->addGroup( "sysop" ); # XXX: make the test user a sysop...
|
2014-02-17 19:24:13 +00:00
|
|
|
|
|
|
|
|
$text = "one";
|
|
|
|
|
$page = $this->newPage( "WikiPageTest_testDoRollback" );
|
2014-04-24 12:50:36 +00:00
|
|
|
$page->doEditContent(
|
|
|
|
|
ContentHandler::makeContent( $text, $page->getTitle(), CONTENT_MODEL_WIKITEXT ),
|
|
|
|
|
"section one",
|
|
|
|
|
EDIT_NEW,
|
|
|
|
|
false,
|
|
|
|
|
$admin
|
|
|
|
|
);
|
2014-02-17 19:24:13 +00:00
|
|
|
$rev1 = $page->getRevision();
|
|
|
|
|
|
|
|
|
|
$user1 = new User();
|
|
|
|
|
$user1->setName( "127.0.1.11" );
|
User group memberships that expire
This patch adds an ug_expiry column to the user_groups table, a timestamp
giving a date when the user group expires. A new UserGroupMembership class,
based on the Block class, manages entries in this table.
When the expiry date passes, the row in user_groups is ignored, and will
eventually be purged from the DB when UserGroupMembership::insert is next
called. Old, expired user group memberships are not kept; instead, the log
entries are available to find the history of these memberships, similar
to the way it has always worked for blocks and protections.
Anyone getting user group info through the User object will get correct
information. However, code that reads the user_groups table directly will
now need to skip over rows with ug_expiry < wfTimestampNow(). See
UsersPager for an example of how to do this.
NULL is used to represent infinite (no) expiry, rather than a string
'infinity' or similar (except in the API). This allows existing user group
assignments and log entries, which are all infinite in duration, to be
treated the same as new, infinite-length memberships, without special
casing everything.
The whole thing is behind the temporary feature flag
$wgDisableUserGroupExpiry, in accordance with the WMF schema change policy.
The opportunity has been taken to refactor some static user-group-related
functions out of User into UserGroupMembership, and also to add a primary
key (ug_user, ug_group) to the user_groups table.
There are a few breaking changes:
- UserRightsProxy-like objects are now required to have a
getGroupMemberships() function.
- $user->mGroups (on a User object) is no longer present.
- Some protected functions in UsersPager are altered or removed.
- The UsersPagerDoBatchLookups hook (unused in any Wikimedia Git-hosted
extension) has a change of parameter.
Bug: T12493
Depends-On: Ia9616e1e35184fed9058d2d39afbe1038f56d7fa
Depends-On: I86eb1d5619347ce54a5f33a591417742ebe5d6f8
Change-Id: I93c955dc7a970f78e32aa503c01c67da30971d1a
2017-01-12 06:07:56 +00:00
|
|
|
$user1->addToDatabase();
|
2015-09-11 13:44:59 +00:00
|
|
|
$user1->addGroup( "sysop" ); # XXX: make the test user a sysop...
|
2014-02-17 19:24:13 +00:00
|
|
|
$text .= "\n\ntwo";
|
|
|
|
|
$page = new WikiPage( $page->getTitle() );
|
2014-04-24 12:50:36 +00:00
|
|
|
$page->doEditContent(
|
|
|
|
|
ContentHandler::makeContent( $text, $page->getTitle(), CONTENT_MODEL_WIKITEXT ),
|
|
|
|
|
"adding section two",
|
|
|
|
|
0,
|
|
|
|
|
false,
|
|
|
|
|
$user1
|
|
|
|
|
);
|
2014-02-17 19:24:13 +00:00
|
|
|
|
|
|
|
|
# now, do a the rollback from the same user was doing the edit before
|
2016-02-17 09:09:32 +00:00
|
|
|
$resultDetails = [];
|
User group memberships that expire
This patch adds an ug_expiry column to the user_groups table, a timestamp
giving a date when the user group expires. A new UserGroupMembership class,
based on the Block class, manages entries in this table.
When the expiry date passes, the row in user_groups is ignored, and will
eventually be purged from the DB when UserGroupMembership::insert is next
called. Old, expired user group memberships are not kept; instead, the log
entries are available to find the history of these memberships, similar
to the way it has always worked for blocks and protections.
Anyone getting user group info through the User object will get correct
information. However, code that reads the user_groups table directly will
now need to skip over rows with ug_expiry < wfTimestampNow(). See
UsersPager for an example of how to do this.
NULL is used to represent infinite (no) expiry, rather than a string
'infinity' or similar (except in the API). This allows existing user group
assignments and log entries, which are all infinite in duration, to be
treated the same as new, infinite-length memberships, without special
casing everything.
The whole thing is behind the temporary feature flag
$wgDisableUserGroupExpiry, in accordance with the WMF schema change policy.
The opportunity has been taken to refactor some static user-group-related
functions out of User into UserGroupMembership, and also to add a primary
key (ug_user, ug_group) to the user_groups table.
There are a few breaking changes:
- UserRightsProxy-like objects are now required to have a
getGroupMemberships() function.
- $user->mGroups (on a User object) is no longer present.
- Some protected functions in UsersPager are altered or removed.
- The UsersPagerDoBatchLookups hook (unused in any Wikimedia Git-hosted
extension) has a change of parameter.
Bug: T12493
Depends-On: Ia9616e1e35184fed9058d2d39afbe1038f56d7fa
Depends-On: I86eb1d5619347ce54a5f33a591417742ebe5d6f8
Change-Id: I93c955dc7a970f78e32aa503c01c67da30971d1a
2017-01-12 06:07:56 +00:00
|
|
|
$token = $user1->getEditToken( 'rollback' );
|
2014-04-24 12:50:36 +00:00
|
|
|
$errors = $page->doRollback(
|
|
|
|
|
$user1->getName(),
|
|
|
|
|
"testing revert same user",
|
|
|
|
|
$token,
|
|
|
|
|
false,
|
|
|
|
|
$resultDetails,
|
|
|
|
|
$admin
|
|
|
|
|
);
|
2014-02-17 19:24:13 +00:00
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
$this->assertEquals( [], $errors, "Rollback failed same user" );
|
2014-02-17 19:24:13 +00:00
|
|
|
|
|
|
|
|
# now, try the rollback
|
2016-02-17 09:09:32 +00:00
|
|
|
$resultDetails = [];
|
User group memberships that expire
This patch adds an ug_expiry column to the user_groups table, a timestamp
giving a date when the user group expires. A new UserGroupMembership class,
based on the Block class, manages entries in this table.
When the expiry date passes, the row in user_groups is ignored, and will
eventually be purged from the DB when UserGroupMembership::insert is next
called. Old, expired user group memberships are not kept; instead, the log
entries are available to find the history of these memberships, similar
to the way it has always worked for blocks and protections.
Anyone getting user group info through the User object will get correct
information. However, code that reads the user_groups table directly will
now need to skip over rows with ug_expiry < wfTimestampNow(). See
UsersPager for an example of how to do this.
NULL is used to represent infinite (no) expiry, rather than a string
'infinity' or similar (except in the API). This allows existing user group
assignments and log entries, which are all infinite in duration, to be
treated the same as new, infinite-length memberships, without special
casing everything.
The whole thing is behind the temporary feature flag
$wgDisableUserGroupExpiry, in accordance with the WMF schema change policy.
The opportunity has been taken to refactor some static user-group-related
functions out of User into UserGroupMembership, and also to add a primary
key (ug_user, ug_group) to the user_groups table.
There are a few breaking changes:
- UserRightsProxy-like objects are now required to have a
getGroupMemberships() function.
- $user->mGroups (on a User object) is no longer present.
- Some protected functions in UsersPager are altered or removed.
- The UsersPagerDoBatchLookups hook (unused in any Wikimedia Git-hosted
extension) has a change of parameter.
Bug: T12493
Depends-On: Ia9616e1e35184fed9058d2d39afbe1038f56d7fa
Depends-On: I86eb1d5619347ce54a5f33a591417742ebe5d6f8
Change-Id: I93c955dc7a970f78e32aa503c01c67da30971d1a
2017-01-12 06:07:56 +00:00
|
|
|
$token = $admin->getEditToken( 'rollback' );
|
2014-04-24 12:50:36 +00:00
|
|
|
$errors = $page->doRollback(
|
|
|
|
|
$user1->getName(),
|
|
|
|
|
"testing revert",
|
|
|
|
|
$token,
|
|
|
|
|
false,
|
|
|
|
|
$resultDetails,
|
|
|
|
|
$admin
|
|
|
|
|
);
|
2014-02-17 19:24:13 +00:00
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
$this->assertEquals( [ [ 'alreadyrolled', 'WikiPageTest testDoRollback',
|
|
|
|
|
'127.0.1.11', 'Admin' ] ], $errors, "Rollback not failed" );
|
2014-02-17 19:24:13 +00:00
|
|
|
|
|
|
|
|
$page = new WikiPage( $page->getTitle() );
|
|
|
|
|
$this->assertEquals( $rev1->getSha1(), $page->getRevision()->getSha1(),
|
2013-02-14 11:56:23 +00:00
|
|
|
"rollback did not revert to the correct revision" );
|
2012-05-14 21:24:18 +00:00
|
|
|
$this->assertEquals( "one", $page->getContent()->getNativeData() );
|
2012-05-02 17:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
2013-02-14 11:56:23 +00:00
|
|
|
public static function provideGetAutoDeleteReason() {
|
2016-02-17 09:09:32 +00:00
|
|
|
return [
|
|
|
|
|
[
|
|
|
|
|
[],
|
2012-05-02 17:35:42 +00:00
|
|
|
false,
|
|
|
|
|
false
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
2012-05-02 17:35:42 +00:00
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
[ "first edit", null ],
|
|
|
|
|
],
|
2012-05-02 17:35:42 +00:00
|
|
|
"/first edit.*only contributor/",
|
|
|
|
|
false
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
2012-05-02 17:35:42 +00:00
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
[ "first edit", null ],
|
|
|
|
|
[ "second edit", null ],
|
|
|
|
|
],
|
2012-05-02 17:35:42 +00:00
|
|
|
"/second edit.*only contributor/",
|
|
|
|
|
true
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
2012-05-02 17:35:42 +00:00
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
[ "first edit", "127.0.2.22" ],
|
|
|
|
|
[ "second edit", "127.0.3.33" ],
|
|
|
|
|
],
|
2012-05-02 17:35:42 +00:00
|
|
|
"/second edit/",
|
|
|
|
|
true
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
2012-05-02 17:35:42 +00:00
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
[
|
2014-04-24 12:50:36 +00:00
|
|
|
"first edit: "
|
|
|
|
|
. "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam "
|
|
|
|
|
. " nonumy eirmod tempor invidunt ut labore et dolore magna "
|
|
|
|
|
. "aliquyam erat, sed diam voluptua. At vero eos et accusam "
|
|
|
|
|
. "et justo duo dolores et ea rebum. Stet clita kasd gubergren, "
|
|
|
|
|
. "no sea takimata sanctus est Lorem ipsum dolor sit amet.'",
|
|
|
|
|
null
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
],
|
2012-05-02 17:35:42 +00:00
|
|
|
'/first edit:.*\.\.\."/',
|
|
|
|
|
false
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
2012-05-02 17:35:42 +00:00
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
[ "first edit", "127.0.2.22" ],
|
|
|
|
|
[ "", "127.0.3.33" ],
|
|
|
|
|
],
|
2012-05-02 17:35:42 +00:00
|
|
|
"/before blanking.*first edit/",
|
|
|
|
|
true
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
2012-05-02 17:35:42 +00:00
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
];
|
2012-05-02 17:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2012-10-08 10:56:20 +00:00
|
|
|
* @dataProvider provideGetAutoDeleteReason
|
2013-10-21 21:09:13 +00:00
|
|
|
* @covers WikiPage::getAutoDeleteReason
|
2012-05-02 17:35:42 +00:00
|
|
|
*/
|
|
|
|
|
public function testGetAutoDeleteReason( $edits, $expectedResult, $expectedHistory ) {
|
|
|
|
|
global $wgUser;
|
|
|
|
|
|
2015-09-11 13:44:59 +00:00
|
|
|
// NOTE: assume Help namespace to contain wikitext
|
2012-09-19 18:07:56 +00:00
|
|
|
$page = $this->newPage( "Help:WikiPageTest_testGetAutoDeleteReason" );
|
2012-05-02 17:35:42 +00:00
|
|
|
|
|
|
|
|
$c = 1;
|
|
|
|
|
|
|
|
|
|
foreach ( $edits as $edit ) {
|
|
|
|
|
$user = new User();
|
|
|
|
|
|
2013-02-14 11:56:23 +00:00
|
|
|
if ( !empty( $edit[1] ) ) {
|
|
|
|
|
$user->setName( $edit[1] );
|
|
|
|
|
} else {
|
|
|
|
|
$user = $wgUser;
|
|
|
|
|
}
|
2012-05-02 17:35:42 +00:00
|
|
|
|
2012-05-13 22:02:29 +00:00
|
|
|
$content = ContentHandler::makeContent( $edit[0], $page->getTitle(), $page->getContentModel() );
|
2012-04-24 16:00:21 +00:00
|
|
|
|
|
|
|
|
$page->doEditContent( $content, "test edit $c", $c < 2 ? EDIT_NEW : 0, false, $user );
|
2012-05-02 17:35:42 +00:00
|
|
|
|
|
|
|
|
$c += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$reason = $page->getAutoDeleteReason( $hasHistory );
|
|
|
|
|
|
2013-02-14 11:56:23 +00:00
|
|
|
if ( is_bool( $expectedResult ) || is_null( $expectedResult ) ) {
|
|
|
|
|
$this->assertEquals( $expectedResult, $reason );
|
|
|
|
|
} else {
|
|
|
|
|
$this->assertTrue( (bool)preg_match( $expectedResult, $reason ),
|
|
|
|
|
"Autosummary didn't match expected pattern $expectedResult: $reason" );
|
|
|
|
|
}
|
2012-05-02 17:35:42 +00:00
|
|
|
|
2012-08-20 19:33:07 +00:00
|
|
|
$this->assertEquals( $expectedHistory, $hasHistory,
|
2013-02-14 11:56:23 +00:00
|
|
|
"expected \$hasHistory to be " . var_export( $expectedHistory, true ) );
|
2012-05-02 17:35:42 +00:00
|
|
|
|
|
|
|
|
$page->doDeleteArticle( "done" );
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-08 10:56:20 +00:00
|
|
|
public static function providePreSaveTransform() {
|
2016-02-17 09:09:32 +00:00
|
|
|
return [
|
|
|
|
|
[ 'hello this is ~~~',
|
2013-02-14 11:56:23 +00:00
|
|
|
"hello this is [[Special:Contributions/127.0.0.1|127.0.0.1]]",
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[ 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
|
2013-02-14 11:56:23 +00:00
|
|
|
'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
];
|
2012-05-02 17:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
2013-10-24 10:54:02 +00:00
|
|
|
/**
|
|
|
|
|
* @covers WikiPage::factory
|
|
|
|
|
*/
|
|
|
|
|
public function testWikiPageFactory() {
|
|
|
|
|
$title = Title::makeTitle( NS_FILE, 'Someimage.png' );
|
|
|
|
|
$page = WikiPage::factory( $title );
|
|
|
|
|
$this->assertEquals( 'WikiFilePage', get_class( $page ) );
|
|
|
|
|
|
|
|
|
|
$title = Title::makeTitle( NS_CATEGORY, 'SomeCategory' );
|
|
|
|
|
$page = WikiPage::factory( $title );
|
|
|
|
|
$this->assertEquals( 'WikiCategoryPage', get_class( $page ) );
|
|
|
|
|
|
|
|
|
|
$title = Title::makeTitle( NS_MAIN, 'SomePage' );
|
|
|
|
|
$page = WikiPage::factory( $title );
|
|
|
|
|
$this->assertEquals( 'WikiPage', get_class( $page ) );
|
|
|
|
|
}
|
2017-06-06 17:39:14 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideCommentMigrationOnDeletion
|
|
|
|
|
* @param int $wstage
|
|
|
|
|
* @param int $rstage
|
|
|
|
|
*/
|
|
|
|
|
public function testCommentMigrationOnDeletion( $wstage, $rstage ) {
|
|
|
|
|
$this->setMwGlobals( 'wgCommentTableSchemaMigrationStage', $wstage );
|
|
|
|
|
$dbr = wfGetDB( DB_REPLICA );
|
|
|
|
|
|
|
|
|
|
$page = $this->createPage(
|
|
|
|
|
"WikiPageTest_testCommentMigrationOnDeletion",
|
|
|
|
|
"foo",
|
|
|
|
|
CONTENT_MODEL_WIKITEXT
|
|
|
|
|
);
|
|
|
|
|
$revid = $page->getLatest();
|
|
|
|
|
if ( $wstage > MIGRATION_OLD ) {
|
|
|
|
|
$comment_id = $dbr->selectField(
|
|
|
|
|
'revision_comment_temp',
|
|
|
|
|
'revcomment_comment_id',
|
|
|
|
|
[ 'revcomment_rev' => $revid ],
|
|
|
|
|
__METHOD__
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$this->setMwGlobals( 'wgCommentTableSchemaMigrationStage', $rstage );
|
|
|
|
|
|
|
|
|
|
$page->doDeleteArticle( "testing deletion" );
|
|
|
|
|
|
|
|
|
|
if ( $rstage > MIGRATION_OLD ) {
|
|
|
|
|
// Didn't leave behind any 'revision_comment_temp' rows
|
|
|
|
|
$n = $dbr->selectField(
|
|
|
|
|
'revision_comment_temp', 'COUNT(*)', [ 'revcomment_rev' => $revid ], __METHOD__
|
|
|
|
|
);
|
|
|
|
|
$this->assertEquals( 0, $n, 'no entry in revision_comment_temp after deletion' );
|
|
|
|
|
|
|
|
|
|
// Copied or upgraded the comment_id, as applicable
|
|
|
|
|
$ar_comment_id = $dbr->selectField(
|
|
|
|
|
'archive',
|
|
|
|
|
'ar_comment_id',
|
|
|
|
|
[ 'ar_rev_id' => $revid ],
|
|
|
|
|
__METHOD__
|
|
|
|
|
);
|
|
|
|
|
if ( $wstage > MIGRATION_OLD ) {
|
|
|
|
|
$this->assertSame( $comment_id, $ar_comment_id );
|
|
|
|
|
} else {
|
|
|
|
|
$this->assertNotEquals( 0, $ar_comment_id );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Copied rev_comment, if applicable
|
|
|
|
|
if ( $rstage <= MIGRATION_WRITE_BOTH && $wstage <= MIGRATION_WRITE_BOTH ) {
|
|
|
|
|
$ar_comment = $dbr->selectField(
|
|
|
|
|
'archive',
|
|
|
|
|
'ar_comment',
|
|
|
|
|
[ 'ar_rev_id' => $revid ],
|
|
|
|
|
__METHOD__
|
|
|
|
|
);
|
|
|
|
|
$this->assertSame( 'testing', $ar_comment );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static function provideCommentMigrationOnDeletion() {
|
|
|
|
|
return [
|
|
|
|
|
[ MIGRATION_OLD, MIGRATION_OLD ],
|
|
|
|
|
[ MIGRATION_OLD, MIGRATION_WRITE_BOTH ],
|
|
|
|
|
[ MIGRATION_OLD, MIGRATION_WRITE_NEW ],
|
|
|
|
|
[ MIGRATION_WRITE_BOTH, MIGRATION_OLD ],
|
|
|
|
|
[ MIGRATION_WRITE_BOTH, MIGRATION_WRITE_BOTH ],
|
|
|
|
|
[ MIGRATION_WRITE_BOTH, MIGRATION_WRITE_NEW ],
|
|
|
|
|
[ MIGRATION_WRITE_BOTH, MIGRATION_NEW ],
|
|
|
|
|
[ MIGRATION_WRITE_NEW, MIGRATION_WRITE_BOTH ],
|
|
|
|
|
[ MIGRATION_WRITE_NEW, MIGRATION_WRITE_NEW ],
|
|
|
|
|
[ MIGRATION_WRITE_NEW, MIGRATION_NEW ],
|
|
|
|
|
[ MIGRATION_NEW, MIGRATION_WRITE_BOTH ],
|
|
|
|
|
[ MIGRATION_NEW, MIGRATION_WRITE_NEW ],
|
|
|
|
|
[ MIGRATION_NEW, MIGRATION_NEW ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-02 17:35:42 +00:00
|
|
|
}
|