parent::__construct( $title, $slots, $wikiId );
Assert::parameterType( 'object', $row, '$row' );
+ $timestamp = wfTimestamp( TS_MW, $row->ar_timestamp );
+ Assert::parameter( is_string( $timestamp ), '$row->rev_timestamp', 'must be a valid timestamp' );
+
$this->mArchiveId = intval( $row->ar_id );
// NOTE: ar_page_id may be different from $this->mTitle->getArticleID() in some cases,
$this->mId = isset( $row->ar_rev_id ) ? intval( $row->ar_rev_id ) : null;
$this->mComment = $comment;
$this->mUser = $user;
- $this->mTimestamp = wfTimestamp( TS_MW, $row->ar_timestamp );
+ $this->mTimestamp = $timestamp;
$this->mMinorEdit = boolval( $row->ar_minor_edit );
$this->mDeleted = intval( $row->ar_deleted );
- $this->mSize = intval( $row->ar_len );
- $this->mSha1 = isset( $row->ar_sha1 ) ? $row->ar_sha1 : null;
+ $this->mSize = isset( $row->ar_len ) ? intval( $row->ar_len ) : null;
+ $this->mSha1 = !empty( $row->ar_sha1 ) ? $row->ar_sha1 : null;
}
/**
* @return int
*/
public function getArchiveId() {
- return $this->mId;
+ return $this->mArchiveId;
}
/**
// allows rev_parent_id to be NULL.
$this->mParentId = isset( $row->rev_parent_id ) ? intval( $row->rev_parent_id ) : null;
$this->mSize = isset( $row->rev_len ) ? intval( $row->rev_len ) : null;
- $this->mSha1 = isset( $row->rev_sha1 ) ? $row->rev_sha1 : null;
+ $this->mSha1 = !empty( $row->rev_sha1 ) ? $row->rev_sha1 : null;
// NOTE: we must not call $this->mTitle->getLatestRevID() here, since the state of
// page_latest may be in limbo during revision creation. In that case, calling
# tests/phpunit/includes/Storage
'MediaWiki\Tests\Storage\RevisionSlotsTest' => "$testDir/phpunit/includes/Storage/RevisionSlotsTest.php",
+ 'MediaWiki\Tests\Storage\RevisionRecordTests' => "$testDir/phpunit/includes/Storage/RevisionRecordTests.php",
# tests/phpunit/languages
'LanguageClassesTestCase' => "$testDir/phpunit/languages/LanguageClassesTestCase.php",
namespace MediaWiki\Tests\Storage;
use CommentStoreComment;
+use InvalidArgumentException;
use MediaWiki\Storage\MutableRevisionRecord;
use MediaWiki\Storage\RevisionAccessException;
use MediaWiki\Storage\RevisionRecord;
use MediaWiki\Storage\SlotRecord;
+use MediaWiki\User\UserIdentityValue;
use MediaWikiTestCase;
+use TextContent;
use Title;
use WikitextContent;
/**
* @covers \MediaWiki\Storage\MutableRevisionRecord
+ * @covers \MediaWiki\Storage\RevisionRecord
*/
class MutableRevisionRecordTest extends MediaWikiTestCase {
- public function testSimpleSetGetId() {
+ use RevisionRecordTests;
+
+ /**
+ * @param array $rowOverrides
+ *
+ * @return MutableRevisionRecord
+ */
+ protected function newRevision( array $rowOverrides = [] ) {
+ $title = Title::newFromText( 'Dummy' );
+ $title->resetArticleID( 17 );
+
+ $user = new UserIdentityValue( 11, 'Tester', 0 );
+ $comment = CommentStoreComment::newUnsavedComment( 'Hello World' );
+
+ $record = new MutableRevisionRecord( $title );
+
+ if ( isset( $rowOverrides['rev_deleted'] ) ) {
+ $record->setVisibility( $rowOverrides['rev_deleted'] );
+ }
+
+ if ( isset( $rowOverrides['rev_id'] ) ) {
+ $record->setId( $rowOverrides['rev_id'] );
+ }
+
+ if ( isset( $rowOverrides['rev_page'] ) ) {
+ $record->setPageId( $rowOverrides['rev_page'] );
+ }
+
+ $record->setContent( 'main', new TextContent( 'Lorem Ipsum' ) );
+ $record->setComment( $comment );
+ $record->setUser( $user );
+
+ return $record;
+ }
+
+ public function provideConstructor() {
+ $title = Title::newFromText( 'Dummy' );
+ $title->resetArticleID( 17 );
+
+ yield [
+ $title,
+ 'acmewiki'
+ ];
+ }
+
+ /**
+ * @dataProvider provideConstructor
+ *
+ * @param Title $title
+ * @param bool $wikiId
+ */
+ public function testConstructorAndGetters(
+ Title $title,
+ $wikiId = false
+ ) {
+ $rec = new MutableRevisionRecord( $title, $wikiId );
+
+ $this->assertSame( $title, $rec->getPageAsLinkTarget(), 'getPageAsLinkTarget' );
+ $this->assertSame( $wikiId, $rec->getWikiId(), 'getWikiId' );
+ }
+
+ public function provideConstructorFailure() {
+ $title = Title::newFromText( 'Dummy' );
+ $title->resetArticleID( 17 );
+
+ yield 'not a wiki id' => [
+ $title,
+ null
+ ];
+ }
+
+ /**
+ * @dataProvider provideConstructorFailure
+ *
+ * @param Title $title
+ * @param bool $wikiId
+ */
+ public function testConstructorFailure(
+ Title $title,
+ $wikiId = false
+ ) {
+ $this->setExpectedException( InvalidArgumentException::class );
+ new MutableRevisionRecord( $title, $wikiId );
+ }
+
+ public function testSetGetId() {
$record = new MutableRevisionRecord( Title::newFromText( 'Foo' ) );
$this->assertNull( $record->getId() );
$record->setId( 888 );
$this->assertSame( 888, $record->getId() );
}
- public function testSimpleSetGetUser() {
+ public function testSetGetUser() {
$record = new MutableRevisionRecord( Title::newFromText( 'Foo' ) );
$user = $this->getTestSysop()->getUser();
$this->assertNull( $record->getUser() );
$this->assertSame( $user, $record->getUser() );
}
- public function testSimpleSetGetPageId() {
+ public function testSetGetPageId() {
$record = new MutableRevisionRecord( Title::newFromText( 'Foo' ) );
$this->assertSame( 0, $record->getPageId() );
$record->setPageId( 999 );
$this->assertSame( 999, $record->getPageId() );
}
- public function testSimpleSetGetParentId() {
+ public function testSetGetParentId() {
$record = new MutableRevisionRecord( Title::newFromText( 'Foo' ) );
$this->assertNull( $record->getParentId() );
$record->setParentId( 100 );
$this->assertSame( 100, $record->getParentId() );
}
- public function testSimpleGetMainContentWhenEmpty() {
+ public function testGetMainContentWhenEmpty() {
$record = new MutableRevisionRecord( Title::newFromText( 'Foo' ) );
$this->setExpectedException( RevisionAccessException::class );
$this->assertNull( $record->getContent( 'main' ) );
}
- public function testSimpleSetGetMainContent() {
+ public function testSetGetMainContent() {
$record = new MutableRevisionRecord( Title::newFromText( 'Foo' ) );
$content = new WikitextContent( 'Badger' );
$record->setContent( 'main', $content );
$this->assertSame( $content, $record->getContent( 'main' ) );
}
- public function testSimpleGetSlotWhenEmpty() {
+ public function testGetSlotWhenEmpty() {
$record = new MutableRevisionRecord( Title::newFromText( 'Foo' ) );
$this->assertFalse( $record->hasSlot( 'main' ) );
$record->getSlot( 'main' );
}
- public function testSimpleSetGetSlot() {
+ public function testSetGetSlot() {
$record = new MutableRevisionRecord( Title::newFromText( 'Foo' ) );
$slot = SlotRecord::newUnsaved(
'main',
$this->assertSame( $slot, $record->getSlot( 'main' ) );
}
- public function testSimpleSetGetMinor() {
+ public function testSetGetMinor() {
$record = new MutableRevisionRecord( Title::newFromText( 'Foo' ) );
$this->assertFalse( $record->isMinor() );
$record->setMinorEdit( true );
$this->assertSame( true, $record->isMinor() );
}
- public function testSimpleSetGetTimestamp() {
+ public function testSetGetTimestamp() {
$record = new MutableRevisionRecord( Title::newFromText( 'Foo' ) );
$this->assertNull( $record->getTimestamp() );
$record->setTimestamp( '20180101010101' );
$this->assertSame( '20180101010101', $record->getTimestamp() );
}
- public function testSimpleSetGetVisibility() {
+ public function testSetGetVisibility() {
$record = new MutableRevisionRecord( Title::newFromText( 'Foo' ) );
$this->assertSame( 0, $record->getVisibility() );
$record->setVisibility( RevisionRecord::DELETED_USER );
$this->assertSame( RevisionRecord::DELETED_USER, $record->getVisibility() );
}
- public function testSimpleSetGetSha1() {
+ public function testSetGetSha1() {
$record = new MutableRevisionRecord( Title::newFromText( 'Foo' ) );
$this->assertSame( 'phoiac9h4m842xq45sp7s6u21eteeq1', $record->getSha1() );
$record->setSha1( 'someHash' );
$this->assertSame( 'someHash', $record->getSha1() );
}
- public function testSimpleSetGetSize() {
+ public function testSetGetSize() {
$record = new MutableRevisionRecord( Title::newFromText( 'Foo' ) );
$this->assertSame( 0, $record->getSize() );
$record->setSize( 775 );
$this->assertSame( 775, $record->getSize() );
}
- public function testSimpleSetGetComment() {
+ public function testSetGetComment() {
$record = new MutableRevisionRecord( Title::newFromText( 'Foo' ) );
$comment = new CommentStoreComment( 1, 'foo' );
$this->assertNull( $record->getComment() );
--- /dev/null
+<?php
+
+namespace MediaWiki\Tests\Storage;
+
+use CommentStoreComment;
+use InvalidArgumentException;
+use MediaWiki\Storage\RevisionRecord;
+use MediaWiki\Storage\RevisionSlots;
+use MediaWiki\Storage\RevisionArchiveRecord;
+use MediaWiki\Storage\SlotRecord;
+use MediaWiki\User\UserIdentity;
+use MediaWiki\User\UserIdentityValue;
+use MediaWikiTestCase;
+use TextContent;
+use Title;
+
+/**
+ * @covers \MediaWiki\Storage\RevisionArchiveRecord
+ * @covers \MediaWiki\Storage\RevisionRecord
+ */
+class RevisionArchiveRecordTest extends MediaWikiTestCase {
+
+ use RevisionRecordTests;
+
+ /**
+ * @param array $rowOverrides
+ *
+ * @return RevisionArchiveRecord
+ */
+ protected function newRevision( array $rowOverrides = [] ) {
+ $title = Title::newFromText( 'Dummy' );
+ $title->resetArticleID( 17 );
+
+ $user = new UserIdentityValue( 11, 'Tester', 0 );
+ $comment = CommentStoreComment::newUnsavedComment( 'Hello World' );
+
+ $main = SlotRecord::newUnsaved( 'main', new TextContent( 'Lorem Ipsum' ) );
+ $aux = SlotRecord::newUnsaved( 'aux', new TextContent( 'Frumious Bandersnatch' ) );
+ $slots = new RevisionSlots( [ $main, $aux ] );
+
+ $row = [
+ 'ar_id' => '5',
+ 'ar_rev_id' => '7',
+ 'ar_page_id' => strval( $title->getArticleID() ),
+ 'ar_timestamp' => '20200101000000',
+ 'ar_deleted' => 0,
+ 'ar_minor_edit' => 0,
+ 'ar_parent_id' => '5',
+ 'ar_len' => $slots->computeSize(),
+ 'ar_sha1' => $slots->computeSha1(),
+ ];
+
+ foreach ( $rowOverrides as $field => $value ) {
+ $field = preg_replace( '/^rev_/', 'ar_', $field );
+ $row[$field] = $value;
+ }
+
+ return new RevisionArchiveRecord( $title, $user, $comment, (object)$row, $slots );
+ }
+
+ public function provideConstructor() {
+ $title = Title::newFromText( 'Dummy' );
+ $title->resetArticleID( 17 );
+
+ $user = new UserIdentityValue( 11, 'Tester', 0 );
+ $comment = CommentStoreComment::newUnsavedComment( 'Hello World' );
+
+ $main = SlotRecord::newUnsaved( 'main', new TextContent( 'Lorem Ipsum' ) );
+ $aux = SlotRecord::newUnsaved( 'aux', new TextContent( 'Frumious Bandersnatch' ) );
+ $slots = new RevisionSlots( [ $main, $aux ] );
+
+ $protoRow = [
+ 'ar_id' => '5',
+ 'ar_rev_id' => '7',
+ 'ar_page_id' => strval( $title->getArticleID() ),
+ 'ar_timestamp' => '20200101000000',
+ 'ar_deleted' => 0,
+ 'ar_minor_edit' => 0,
+ 'ar_parent_id' => '5',
+ 'ar_len' => $slots->computeSize(),
+ 'ar_sha1' => $slots->computeSha1(),
+ ];
+
+ $row = $protoRow;
+ yield 'all info' => [
+ $title,
+ $user,
+ $comment,
+ (object)$row,
+ $slots,
+ 'acmewiki'
+ ];
+
+ $row = $protoRow;
+ $row['ar_minor_edit'] = '1';
+ $row['ar_deleted'] = strval( RevisionRecord::DELETED_USER );
+
+ yield 'minor deleted' => [
+ $title,
+ $user,
+ $comment,
+ (object)$row,
+ $slots
+ ];
+
+ $row = $protoRow;
+ unset( $row['ar_parent'] );
+
+ yield 'no parent' => [
+ $title,
+ $user,
+ $comment,
+ (object)$row,
+ $slots
+ ];
+
+ $row = $protoRow;
+ $row['ar_len'] = null;
+ $row['ar_sha1'] = '';
+
+ yield 'ar_len is null, ar_sha1 is ""' => [
+ $title,
+ $user,
+ $comment,
+ (object)$row,
+ $slots
+ ];
+
+ $row = $protoRow;
+ yield 'no length, no hash' => [
+ Title::newFromText( 'DummyDoesNotExist' ),
+ $user,
+ $comment,
+ (object)$row,
+ $slots
+ ];
+ }
+
+ /**
+ * @dataProvider provideConstructor
+ *
+ * @param Title $title
+ * @param UserIdentity $user
+ * @param CommentStoreComment $comment
+ * @param object $row
+ * @param RevisionSlots $slots
+ * @param bool $wikiId
+ */
+ public function testConstructorAndGetters(
+ Title $title,
+ UserIdentity $user,
+ CommentStoreComment $comment,
+ $row,
+ RevisionSlots $slots,
+ $wikiId = false
+ ) {
+ $rec = new RevisionArchiveRecord( $title, $user, $comment, $row, $slots, $wikiId );
+
+ $this->assertSame( $title, $rec->getPageAsLinkTarget(), 'getPageAsLinkTarget' );
+ $this->assertSame( $user, $rec->getUser( RevisionRecord::RAW ), 'getUser' );
+ $this->assertSame( $comment, $rec->getComment(), 'getComment' );
+
+ $this->assertSame( $slots->getSlotRoles(), $rec->getSlotRoles(), 'getSlotRoles' );
+ $this->assertSame( $wikiId, $rec->getWikiId(), 'getWikiId' );
+
+ $this->assertSame( (int)$row->ar_id, $rec->getArchiveId(), 'getArchiveId' );
+ $this->assertSame( (int)$row->ar_rev_id, $rec->getId(), 'getId' );
+ $this->assertSame( (int)$row->ar_page_id, $rec->getPageId(), 'getId' );
+ $this->assertSame( $row->ar_timestamp, $rec->getTimestamp(), 'getTimestamp' );
+ $this->assertSame( (int)$row->ar_deleted, $rec->getVisibility(), 'getVisibility' );
+ $this->assertSame( (bool)$row->ar_minor_edit, $rec->isMinor(), 'getIsMinor' );
+
+ if ( isset( $row->ar_parent_id ) ) {
+ $this->assertSame( (int)$row->ar_parent_id, $rec->getParentId(), 'getParentId' );
+ } else {
+ $this->assertSame( 0, $rec->getParentId(), 'getParentId' );
+ }
+
+ if ( isset( $row->ar_len ) ) {
+ $this->assertSame( (int)$row->ar_len, $rec->getSize(), 'getSize' );
+ } else {
+ $this->assertSame( $slots->computeSize(), $rec->getSize(), 'getSize' );
+ }
+
+ if ( !empty( $row->ar_sha1 ) ) {
+ $this->assertSame( $row->ar_sha1, $rec->getSha1(), 'getSha1' );
+ } else {
+ $this->assertSame( $slots->computeSha1(), $rec->getSha1(), 'getSha1' );
+ }
+ }
+
+ public function provideConstructorFailure() {
+ $title = Title::newFromText( 'Dummy' );
+ $title->resetArticleID( 17 );
+
+ $user = new UserIdentityValue( 11, 'Tester', 0 );
+
+ $comment = CommentStoreComment::newUnsavedComment( 'Hello World' );
+
+ $main = SlotRecord::newUnsaved( 'main', new TextContent( 'Lorem Ipsum' ) );
+ $aux = SlotRecord::newUnsaved( 'aux', new TextContent( 'Frumious Bandersnatch' ) );
+ $slots = new RevisionSlots( [ $main, $aux ] );
+
+ $protoRow = [
+ 'ar_id' => '5',
+ 'ar_rev_id' => '7',
+ 'ar_page_id' => strval( $title->getArticleID() ),
+ 'ar_timestamp' => '20200101000000',
+ 'ar_deleted' => 0,
+ 'ar_minor_edit' => 0,
+ 'ar_parent_id' => '5',
+ 'ar_len' => $slots->computeSize(),
+ 'ar_sha1' => $slots->computeSha1(),
+ ];
+
+ yield 'not a row' => [
+ $title,
+ $user,
+ $comment,
+ 'not a row',
+ $slots,
+ 'acmewiki'
+ ];
+
+ $row = $protoRow;
+ $row['ar_timestamp'] = 'kittens';
+
+ yield 'bad timestamp' => [
+ $title,
+ $user,
+ $comment,
+ (object)$row,
+ $slots
+ ];
+
+ $row = $protoRow;
+
+ yield 'bad wiki' => [
+ $title,
+ $user,
+ $comment,
+ (object)$row,
+ $slots,
+ 12345
+ ];
+
+ // NOTE: $title->getArticleID does *not* have to match ar_page_id in all cases!
+ }
+
+ /**
+ * @dataProvider provideConstructorFailure
+ *
+ * @param Title $title
+ * @param UserIdentity $user
+ * @param CommentStoreComment $comment
+ * @param object $row
+ * @param RevisionSlots $slots
+ * @param bool $wikiId
+ */
+ public function testConstructorFailure(
+ Title $title,
+ UserIdentity $user,
+ CommentStoreComment $comment,
+ $row,
+ RevisionSlots $slots,
+ $wikiId = false
+ ) {
+ $this->setExpectedException( InvalidArgumentException::class );
+ new RevisionArchiveRecord( $title, $user, $comment, $row, $slots, $wikiId );
+ }
+
+}
--- /dev/null
+<?php
+
+namespace MediaWiki\Tests\Storage;
+
+use CommentStoreComment;
+use LogicException;
+use MediaWiki\Storage\RevisionRecord;
+use MediaWiki\Storage\RevisionSlots;
+use MediaWiki\Storage\RevisionStoreRecord;
+use MediaWiki\Storage\SlotRecord;
+use MediaWiki\Storage\SuppressedDataException;
+use MediaWiki\User\UserIdentityValue;
+use TextContent;
+use Title;
+
+// PHPCS should not complain about @covers and @dataProvider being used in traits, see T192384
+// phpcs:disable MediaWiki.Commenting.PhpunitAnnotations.NotTestClass
+
+/**
+ * @covers \MediaWiki\Storage\RevisionRecord
+ *
+ * @note Expects to be used in classes that extend MediaWikiTestCase.
+ */
+trait RevisionRecordTests {
+
+ /**
+ * @param array $rowOverrides
+ *
+ * @return RevisionRecord
+ */
+ protected abstract function newRevision( array $rowOverrides = [] );
+
+ private function provideAudienceCheckData( $field ) {
+ yield 'field accessible for oversighter (ALL)' => [
+ RevisionRecord::SUPPRESSED_ALL,
+ [ 'oversight' ],
+ true,
+ false
+ ];
+
+ yield 'field accessible for oversighter' => [
+ RevisionRecord::DELETED_RESTRICTED | $field,
+ [ 'oversight' ],
+ true,
+ false
+ ];
+
+ yield 'field not accessible for sysops (ALL)' => [
+ RevisionRecord::SUPPRESSED_ALL,
+ [ 'sysop' ],
+ false,
+ false
+ ];
+
+ yield 'field not accessible for sysops' => [
+ RevisionRecord::DELETED_RESTRICTED | $field,
+ [ 'sysop' ],
+ false,
+ false
+ ];
+
+ yield 'field accessible for sysops' => [
+ $field,
+ [ 'sysop' ],
+ true,
+ false
+ ];
+
+ yield 'field suppressed for logged in users' => [
+ $field,
+ [ 'user' ],
+ false,
+ false
+ ];
+
+ yield 'unrelated field suppressed' => [
+ $field === RevisionRecord::DELETED_COMMENT
+ ? RevisionRecord::DELETED_USER
+ : RevisionRecord::DELETED_COMMENT,
+ [ 'user' ],
+ true,
+ true
+ ];
+
+ yield 'nothing suppressed' => [
+ 0,
+ [ 'user' ],
+ true,
+ true
+ ];
+ }
+
+ public function testSerialization_fails() {
+ $this->setExpectedException( LogicException::class );
+ $rev = $this->newRevision();
+ serialize( $rev );
+ }
+
+ public function provideGetComment_audience() {
+ return $this->provideAudienceCheckData( RevisionRecord::DELETED_COMMENT );
+ }
+
+ private function forceStandardPermissions() {
+ $this->setMwGlobals(
+ 'wgGroupPermissions',
+ [
+ 'user' => [
+ 'viewsuppressed' => false,
+ 'suppressrevision' => false,
+ 'deletedtext' => false,
+ 'deletedhistory' => false,
+ ],
+ 'sysop' => [
+ 'viewsuppressed' => false,
+ 'suppressrevision' => false,
+ 'deletedtext' => true,
+ 'deletedhistory' => true,
+ ],
+ 'oversight' => [
+ 'deletedtext' => true,
+ 'deletedhistory' => true,
+ 'viewsuppressed' => true,
+ 'suppressrevision' => true,
+ ],
+ ]
+ );
+ }
+
+ /**
+ * @dataProvider provideGetComment_audience
+ */
+ public function testGetComment_audience( $visibility, $groups, $userCan, $publicCan ) {
+ $this->forceStandardPermissions();
+
+ $user = $this->getTestUser( $groups )->getUser();
+ $rev = $this->newRevision( [ 'rev_deleted' => $visibility ] );
+
+ $this->assertNotNull( $rev->getComment( RevisionRecord::RAW ), 'raw can' );
+
+ $this->assertSame(
+ $publicCan,
+ $rev->getComment( RevisionRecord::FOR_PUBLIC ) !== null,
+ 'public can'
+ );
+ $this->assertSame(
+ $userCan,
+ $rev->getComment( RevisionRecord::FOR_THIS_USER, $user ) !== null,
+ 'user can'
+ );
+ }
+
+ public function provideGetUser_audience() {
+ return $this->provideAudienceCheckData( RevisionRecord::DELETED_USER );
+ }
+
+ /**
+ * @dataProvider provideGetUser_audience
+ */
+ public function testGetUser_audience( $visibility, $groups, $userCan, $publicCan ) {
+ $this->forceStandardPermissions();
+
+ $user = $this->getTestUser( $groups )->getUser();
+ $rev = $this->newRevision( [ 'rev_deleted' => $visibility ] );
+
+ $this->assertNotNull( $rev->getUser( RevisionRecord::RAW ), 'raw can' );
+
+ $this->assertSame(
+ $publicCan,
+ $rev->getUser( RevisionRecord::FOR_PUBLIC ) !== null,
+ 'public can'
+ );
+ $this->assertSame(
+ $userCan,
+ $rev->getUser( RevisionRecord::FOR_THIS_USER, $user ) !== null,
+ 'user can'
+ );
+ }
+
+ public function provideGetSlot_audience() {
+ return $this->provideAudienceCheckData( RevisionRecord::DELETED_TEXT );
+ }
+
+ /**
+ * @dataProvider provideGetSlot_audience
+ */
+ public function testGetSlot_audience( $visibility, $groups, $userCan, $publicCan ) {
+ $this->forceStandardPermissions();
+
+ $user = $this->getTestUser( $groups )->getUser();
+ $rev = $this->newRevision( [ 'rev_deleted' => $visibility ] );
+
+ // NOTE: slot meta-data is never suppressed, just the content is!
+ $this->assertTrue( $rev->hasSlot( 'main' ), 'hasSlot is never suppressed' );
+ $this->assertNotNull( $rev->getSlot( 'main', RevisionRecord::RAW ), 'raw meta' );
+ $this->assertNotNull( $rev->getSlot( 'main', RevisionRecord::FOR_PUBLIC ), 'public meta' );
+
+ $this->assertNotNull(
+ $rev->getSlot( 'main', RevisionRecord::FOR_THIS_USER, $user ),
+ 'user can'
+ );
+
+ try {
+ $rev->getSlot( 'main', RevisionRecord::FOR_PUBLIC )->getContent();
+ $exception = null;
+ } catch ( SuppressedDataException $ex ) {
+ $exception = $ex;
+ }
+
+ $this->assertSame(
+ $publicCan,
+ $exception === null,
+ 'public can'
+ );
+
+ try {
+ $rev->getSlot( 'main', RevisionRecord::FOR_THIS_USER, $user )->getContent();
+ $exception = null;
+ } catch ( SuppressedDataException $ex ) {
+ $exception = $ex;
+ }
+
+ $this->assertSame(
+ $userCan,
+ $exception === null,
+ 'user can'
+ );
+ }
+
+ /**
+ * @dataProvider provideGetSlot_audience
+ */
+ public function testGetContent_audience( $visibility, $groups, $userCan, $publicCan ) {
+ $this->forceStandardPermissions();
+
+ $user = $this->getTestUser( $groups )->getUser();
+ $rev = $this->newRevision( [ 'rev_deleted' => $visibility ] );
+
+ $this->assertNotNull( $rev->getContent( 'main', RevisionRecord::RAW ), 'raw can' );
+
+ $this->assertSame(
+ $publicCan,
+ $rev->getContent( 'main', RevisionRecord::FOR_PUBLIC ) !== null,
+ 'public can'
+ );
+ $this->assertSame(
+ $userCan,
+ $rev->getContent( 'main', RevisionRecord::FOR_THIS_USER, $user ) !== null,
+ 'user can'
+ );
+ }
+
+ public function testGetSlot() {
+ $rev = $this->newRevision();
+
+ $slot = $rev->getSlot( 'main' );
+ $this->assertNotNull( $slot, 'getSlot()' );
+ $this->assertSame( 'main', $slot->getRole(), 'getRole()' );
+ }
+
+ public function testHasSlot() {
+ $rev = $this->newRevision();
+
+ $this->assertTrue( $rev->hasSlot( 'main' ) );
+ $this->assertFalse( $rev->hasSlot( 'xyz' ) );
+ }
+
+ public function testGetContent() {
+ $rev = $this->newRevision();
+
+ $content = $rev->getSlot( 'main' );
+ $this->assertNotNull( $content, 'getContent()' );
+ $this->assertSame( CONTENT_MODEL_TEXT, $content->getModel(), 'getModel()' );
+ }
+
+ public function provideUserCanBitfield() {
+ yield [ 0, 0, [], null, true ];
+ // Bitfields match, user has no permissions
+ yield [
+ RevisionRecord::DELETED_TEXT,
+ RevisionRecord::DELETED_TEXT,
+ [],
+ null,
+ false
+ ];
+ yield [
+ RevisionRecord::DELETED_COMMENT,
+ RevisionRecord::DELETED_COMMENT,
+ [],
+ null,
+ false,
+ ];
+ yield [
+ RevisionRecord::DELETED_USER,
+ RevisionRecord::DELETED_USER,
+ [],
+ null,
+ false
+ ];
+ yield [
+ RevisionRecord::DELETED_RESTRICTED,
+ RevisionRecord::DELETED_RESTRICTED,
+ [],
+ null,
+ false,
+ ];
+ // Bitfields match, user (admin) does have permissions
+ yield [
+ RevisionRecord::DELETED_TEXT,
+ RevisionRecord::DELETED_TEXT,
+ [ 'sysop' ],
+ null,
+ true,
+ ];
+ yield [
+ RevisionRecord::DELETED_COMMENT,
+ RevisionRecord::DELETED_COMMENT,
+ [ 'sysop' ],
+ null,
+ true,
+ ];
+ yield [
+ RevisionRecord::DELETED_USER,
+ RevisionRecord::DELETED_USER,
+ [ 'sysop' ],
+ null,
+ true,
+ ];
+ // Bitfields match, user (admin) does not have permissions
+ yield [
+ RevisionRecord::DELETED_RESTRICTED,
+ RevisionRecord::DELETED_RESTRICTED,
+ [ 'sysop' ],
+ null,
+ false,
+ ];
+ // Bitfields match, user (oversight) does have permissions
+ yield [
+ RevisionRecord::DELETED_RESTRICTED,
+ RevisionRecord::DELETED_RESTRICTED,
+ [ 'oversight' ],
+ null,
+ true,
+ ];
+ // Check permissions using the title
+ yield [
+ RevisionRecord::DELETED_TEXT,
+ RevisionRecord::DELETED_TEXT,
+ [ 'sysop' ],
+ Title::newFromText( __METHOD__ ),
+ true,
+ ];
+ yield [
+ RevisionRecord::DELETED_TEXT,
+ RevisionRecord::DELETED_TEXT,
+ [],
+ Title::newFromText( __METHOD__ ),
+ false,
+ ];
+ }
+
+ /**
+ * @dataProvider provideUserCanBitfield
+ * @covers \MediaWiki\Storage\RevisionRecord::userCanBitfield
+ */
+ public function testUserCanBitfield( $bitField, $field, $userGroups, $title, $expected ) {
+ $this->forceStandardPermissions();
+
+ $user = $this->getTestUser( $userGroups )->getUser();
+
+ $this->assertSame(
+ $expected,
+ RevisionRecord::userCanBitfield( $bitField, $field, $user, $title )
+ );
+ }
+
+ public function provideHasSameContent() {
+ /**
+ * @param SlotRecord[] $slots
+ * @param int $revId
+ * @return RevisionStoreRecord
+ */
+ $recordCreator = function ( array $slots, $revId ) {
+ $title = Title::newFromText( 'provideHasSameContent' );
+ $title->resetArticleID( 19 );
+ $slots = new RevisionSlots( $slots );
+
+ return new RevisionStoreRecord(
+ $title,
+ new UserIdentityValue( 11, __METHOD__, 0 ),
+ CommentStoreComment::newUnsavedComment( __METHOD__ ),
+ (object)[
+ 'rev_id' => strval( $revId ),
+ 'rev_page' => strval( $title->getArticleID() ),
+ 'rev_timestamp' => '20200101000000',
+ 'rev_deleted' => 0,
+ 'rev_minor_edit' => 0,
+ 'rev_parent_id' => '5',
+ 'rev_len' => $slots->computeSize(),
+ 'rev_sha1' => $slots->computeSha1(),
+ 'page_latest' => '18',
+ ],
+ $slots
+ );
+ };
+
+ // Create some slots with content
+ $mainA = SlotRecord::newUnsaved( 'main', new TextContent( 'A' ) );
+ $mainB = SlotRecord::newUnsaved( 'main', new TextContent( 'B' ) );
+ $auxA = SlotRecord::newUnsaved( 'aux', new TextContent( 'A' ) );
+ $auxB = SlotRecord::newUnsaved( 'aux', new TextContent( 'A' ) );
+
+ $initialRecord = $recordCreator( [ $mainA ], 12 );
+
+ return [
+ 'same record object' => [
+ true,
+ $initialRecord,
+ $initialRecord,
+ ],
+ 'same record content, different object' => [
+ true,
+ $recordCreator( [ $mainA ], 12 ),
+ $recordCreator( [ $mainA ], 13 ),
+ ],
+ 'same record content, aux slot, different object' => [
+ true,
+ $recordCreator( [ $auxA ], 12 ),
+ $recordCreator( [ $auxB ], 13 ),
+ ],
+ 'different content' => [
+ false,
+ $recordCreator( [ $mainA ], 12 ),
+ $recordCreator( [ $mainB ], 13 ),
+ ],
+ 'different content and number of slots' => [
+ false,
+ $recordCreator( [ $mainA ], 12 ),
+ $recordCreator( [ $mainA, $mainB ], 13 ),
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider provideHasSameContent
+ * @covers \MediaWiki\Storage\RevisionRecord::hasSameContent
+ * @group Database
+ */
+ public function testHasSameContent(
+ $expected,
+ RevisionRecord $record1,
+ RevisionRecord $record2
+ ) {
+ $this->assertSame(
+ $expected,
+ $record1->hasSameContent( $record2 )
+ );
+ }
+
+ public function provideIsDeleted() {
+ yield 'no deletion' => [
+ 0,
+ [
+ RevisionRecord::DELETED_TEXT => false,
+ RevisionRecord::DELETED_COMMENT => false,
+ RevisionRecord::DELETED_USER => false,
+ RevisionRecord::DELETED_RESTRICTED => false,
+ ]
+ ];
+ yield 'text deleted' => [
+ RevisionRecord::DELETED_TEXT,
+ [
+ RevisionRecord::DELETED_TEXT => true,
+ RevisionRecord::DELETED_COMMENT => false,
+ RevisionRecord::DELETED_USER => false,
+ RevisionRecord::DELETED_RESTRICTED => false,
+ ]
+ ];
+ yield 'text and comment deleted' => [
+ RevisionRecord::DELETED_TEXT + RevisionRecord::DELETED_COMMENT,
+ [
+ RevisionRecord::DELETED_TEXT => true,
+ RevisionRecord::DELETED_COMMENT => true,
+ RevisionRecord::DELETED_USER => false,
+ RevisionRecord::DELETED_RESTRICTED => false,
+ ]
+ ];
+ yield 'all 4 deleted' => [
+ RevisionRecord::DELETED_TEXT +
+ RevisionRecord::DELETED_COMMENT +
+ RevisionRecord::DELETED_RESTRICTED +
+ RevisionRecord::DELETED_USER,
+ [
+ RevisionRecord::DELETED_TEXT => true,
+ RevisionRecord::DELETED_COMMENT => true,
+ RevisionRecord::DELETED_USER => true,
+ RevisionRecord::DELETED_RESTRICTED => true,
+ ]
+ ];
+ }
+
+ /**
+ * @dataProvider provideIsDeleted
+ * @covers \MediaWiki\Storage\RevisionRecord::isDeleted
+ */
+ public function testIsDeleted( $revDeleted, $assertionMap ) {
+ $rev = $this->newRevision( [ 'rev_deleted' => $revDeleted ] );
+ foreach ( $assertionMap as $deletionLevel => $expected ) {
+ $this->assertSame( $expected, $rev->isDeleted( $deletionLevel ) );
+ }
+ }
+
+}
use CommentStoreComment;
use InvalidArgumentException;
-use LogicException;
use MediaWiki\Storage\RevisionRecord;
use MediaWiki\Storage\RevisionSlots;
use MediaWiki\Storage\RevisionStoreRecord;
use MediaWiki\Storage\SlotRecord;
-use MediaWiki\Storage\SuppressedDataException;
use MediaWiki\User\UserIdentity;
use MediaWiki\User\UserIdentityValue;
use MediaWikiTestCase;
/**
* @covers \MediaWiki\Storage\RevisionStoreRecord
+ * @covers \MediaWiki\Storage\RevisionRecord
*/
class RevisionStoreRecordTest extends MediaWikiTestCase {
+ use RevisionRecordTests;
+
/**
* @param array $rowOverrides
*
* @return RevisionStoreRecord
*/
- public function newRevision( array $rowOverrides = [] ) {
+ protected function newRevision( array $rowOverrides = [] ) {
$title = Title::newFromText( 'Dummy' );
$title->resetArticleID( 17 );
];
$row = $protoRow;
- unset( $row['rev_len'] );
- unset( $row['rev_sha1'] );
+ $row['rev_len'] = null;
+ $row['rev_sha1'] = '';
- yield 'no length, no hash' => [
+ yield 'rev_len is null, rev_sha1 is ""' => [
$title,
$user,
$comment,
$this->assertSame( $slots->computeSize(), $rec->getSize(), 'getSize' );
}
- if ( isset( $row->rev_sha1 ) ) {
+ if ( !empty( $row->rev_sha1 ) ) {
$this->assertSame( $row->rev_sha1, $rec->getSha1(), 'getSha1' );
} else {
$this->assertSame( $slots->computeSha1(), $rec->getSha1(), 'getSha1' );
new RevisionStoreRecord( $title, $user, $comment, $row, $slots, $wikiId );
}
- private function provideAudienceCheckData( $field ) {
- yield 'field accessible for oversighter (ALL)' => [
- RevisionRecord::SUPPRESSED_ALL,
- [ 'oversight' ],
- true,
- false
- ];
-
- yield 'field accessible for oversighter' => [
- RevisionRecord::DELETED_RESTRICTED | $field,
- [ 'oversight' ],
- true,
- false
- ];
-
- yield 'field not accessible for sysops (ALL)' => [
- RevisionRecord::SUPPRESSED_ALL,
- [ 'sysop' ],
- false,
- false
- ];
-
- yield 'field not accessible for sysops' => [
- RevisionRecord::DELETED_RESTRICTED | $field,
- [ 'sysop' ],
- false,
- false
- ];
-
- yield 'field accessible for sysops' => [
- $field,
- [ 'sysop' ],
+ public function provideIsCurrent() {
+ yield [
+ [
+ 'rev_id' => 11,
+ 'page_latest' => 11,
+ ],
true,
- false
];
-
- yield 'field suppressed for logged in users' => [
- $field,
- [ 'user' ],
+ yield [
+ [
+ 'rev_id' => 11,
+ 'page_latest' => 10,
+ ],
false,
- false
- ];
-
- yield 'unrelated field suppressed' => [
- $field === RevisionRecord::DELETED_COMMENT
- ? RevisionRecord::DELETED_USER
- : RevisionRecord::DELETED_COMMENT,
- [ 'user' ],
- true,
- true
- ];
-
- yield 'nothing suppressed' => [
- 0,
- [ 'user' ],
- true,
- true
];
}
- public function testSerialization_fails() {
- $this->setExpectedException( LogicException::class );
- $rev = $this->newRevision();
- serialize( $rev );
- }
-
- public function provideGetComment_audience() {
- return $this->provideAudienceCheckData( RevisionRecord::DELETED_COMMENT );
- }
-
- private function forceStandardPermissions() {
- $this->setMwGlobals(
- 'wgGroupPermissions',
- [
- 'user' => [
- 'viewsuppressed' => false,
- 'suppressrevision' => false,
- 'deletedtext' => false,
- 'deletedhistory' => false,
- ],
- 'sysop' => [
- 'viewsuppressed' => false,
- 'suppressrevision' => false,
- 'deletedtext' => true,
- 'deletedhistory' => true,
- ],
- 'oversight' => [
- 'deletedtext' => true,
- 'deletedhistory' => true,
- 'viewsuppressed' => true,
- 'suppressrevision' => true,
- ],
- ]
- );
- }
-
/**
- * @dataProvider provideGetComment_audience
+ * @dataProvider provideIsCurrent
*/
- public function testGetComment_audience( $visibility, $groups, $userCan, $publicCan ) {
- $this->forceStandardPermissions();
-
- $user = $this->getTestUser( $groups )->getUser();
- $rev = $this->newRevision( [ 'rev_deleted' => $visibility ] );
-
- $this->assertNotNull( $rev->getComment( RevisionRecord::RAW ), 'raw can' );
+ public function testIsCurrent( $row, $current ) {
+ $rev = $this->newRevision( $row );
- $this->assertSame(
- $publicCan,
- $rev->getComment( RevisionRecord::FOR_PUBLIC ) !== null,
- 'public can'
- );
- $this->assertSame(
- $userCan,
- $rev->getComment( RevisionRecord::FOR_THIS_USER, $user ) !== null,
- 'user can'
- );
- }
-
- public function provideGetUser_audience() {
- return $this->provideAudienceCheckData( RevisionRecord::DELETED_USER );
- }
-
- /**
- * @dataProvider provideGetUser_audience
- */
- public function testGetUser_audience( $visibility, $groups, $userCan, $publicCan ) {
- $this->forceStandardPermissions();
-
- $user = $this->getTestUser( $groups )->getUser();
- $rev = $this->newRevision( [ 'rev_deleted' => $visibility ] );
-
- $this->assertNotNull( $rev->getUser( RevisionRecord::RAW ), 'raw can' );
-
- $this->assertSame(
- $publicCan,
- $rev->getUser( RevisionRecord::FOR_PUBLIC ) !== null,
- 'public can'
- );
- $this->assertSame(
- $userCan,
- $rev->getUser( RevisionRecord::FOR_THIS_USER, $user ) !== null,
- 'user can'
- );
- }
-
- public function provideGetSlot_audience() {
- return $this->provideAudienceCheckData( RevisionRecord::DELETED_TEXT );
- }
-
- /**
- * @dataProvider provideGetSlot_audience
- */
- public function testGetSlot_audience( $visibility, $groups, $userCan, $publicCan ) {
- $this->forceStandardPermissions();
-
- $user = $this->getTestUser( $groups )->getUser();
- $rev = $this->newRevision( [ 'rev_deleted' => $visibility ] );
-
- // NOTE: slot meta-data is never suppressed, just the content is!
- $this->assertTrue( $rev->hasSlot( 'main' ), 'hasSlot is never suppressed' );
- $this->assertNotNull( $rev->getSlot( 'main', RevisionRecord::RAW ), 'raw meta' );
- $this->assertNotNull( $rev->getSlot( 'main', RevisionRecord::FOR_PUBLIC ), 'public meta' );
-
- $this->assertNotNull(
- $rev->getSlot( 'main', RevisionRecord::FOR_THIS_USER, $user ),
- 'user can'
- );
-
- try {
- $rev->getSlot( 'main', RevisionRecord::FOR_PUBLIC )->getContent();
- $exception = null;
- } catch ( SuppressedDataException $ex ) {
- $exception = $ex;
- }
-
- $this->assertSame(
- $publicCan,
- $exception === null,
- 'public can'
- );
-
- try {
- $rev->getSlot( 'main', RevisionRecord::FOR_THIS_USER, $user )->getContent();
- $exception = null;
- } catch ( SuppressedDataException $ex ) {
- $exception = $ex;
- }
-
- $this->assertSame(
- $userCan,
- $exception === null,
- 'user can'
- );
+ $this->assertSame( $current, $rev->isCurrent(), 'isCurrent()' );
}
public function provideGetSlot_audience_latest() {
]
);
- // sanity check
- $this->assertTrue( $rev->isCurrent(), 'isCurrent()' );
-
// NOTE: slot meta-data is never suppressed, just the content is!
$this->assertNotNull( $rev->getSlot( 'main', RevisionRecord::RAW ), 'raw can' );
$this->assertNotNull( $rev->getSlot( 'main', RevisionRecord::FOR_PUBLIC ), 'public can' );
'user can'
);
+ $rev->getSlot( 'main', RevisionRecord::RAW )->getContent();
// NOTE: the content of the current revision is never suppressed!
// Check that getContent() doesn't throw SuppressedDataException
- $rev->getSlot( 'main', RevisionRecord::RAW )->getContent();
$rev->getSlot( 'main', RevisionRecord::FOR_PUBLIC )->getContent();
$rev->getSlot( 'main', RevisionRecord::FOR_THIS_USER, $user )->getContent();
}
- /**
- * @dataProvider provideGetSlot_audience
- */
- public function testGetContent_audience( $visibility, $groups, $userCan, $publicCan ) {
- $this->forceStandardPermissions();
-
- $user = $this->getTestUser( $groups )->getUser();
- $rev = $this->newRevision( [ 'rev_deleted' => $visibility ] );
-
- $this->assertNotNull( $rev->getContent( 'main', RevisionRecord::RAW ), 'raw can' );
-
- $this->assertSame(
- $publicCan,
- $rev->getContent( 'main', RevisionRecord::FOR_PUBLIC ) !== null,
- 'public can'
- );
- $this->assertSame(
- $userCan,
- $rev->getContent( 'main', RevisionRecord::FOR_THIS_USER, $user ) !== null,
- 'user can'
- );
- }
-
- public function testGetSlot() {
- $rev = $this->newRevision();
-
- $slot = $rev->getSlot( 'main' );
- $this->assertNotNull( $slot, 'getSlot()' );
- $this->assertSame( 'main', $slot->getRole(), 'getRole()' );
- }
-
- public function testHasSlot() {
- $rev = $this->newRevision();
-
- $this->assertTrue( $rev->hasSlot( 'main' ) );
- $this->assertFalse( $rev->hasSlot( 'xyz' ) );
- }
-
- public function testGetContent() {
- $rev = $this->newRevision();
-
- $content = $rev->getSlot( 'main' );
- $this->assertNotNull( $content, 'getContent()' );
- $this->assertSame( CONTENT_MODEL_TEXT, $content->getModel(), 'getModel()' );
- }
-
- public function provideUserCanBitfield() {
- yield [ 0, 0, [], null, true ];
- // Bitfields match, user has no permissions
- yield [
- RevisionRecord::DELETED_TEXT,
- RevisionRecord::DELETED_TEXT,
- [],
- null,
- false
- ];
- yield [
- RevisionRecord::DELETED_COMMENT,
- RevisionRecord::DELETED_COMMENT,
- [],
- null,
- false,
- ];
- yield [
- RevisionRecord::DELETED_USER,
- RevisionRecord::DELETED_USER,
- [],
- null,
- false
- ];
- yield [
- RevisionRecord::DELETED_RESTRICTED,
- RevisionRecord::DELETED_RESTRICTED,
- [],
- null,
- false,
- ];
- // Bitfields match, user (admin) does have permissions
- yield [
- RevisionRecord::DELETED_TEXT,
- RevisionRecord::DELETED_TEXT,
- [ 'sysop' ],
- null,
- true,
- ];
- yield [
- RevisionRecord::DELETED_COMMENT,
- RevisionRecord::DELETED_COMMENT,
- [ 'sysop' ],
- null,
- true,
- ];
- yield [
- RevisionRecord::DELETED_USER,
- RevisionRecord::DELETED_USER,
- [ 'sysop' ],
- null,
- true,
- ];
- // Bitfields match, user (admin) does not have permissions
- yield [
- RevisionRecord::DELETED_RESTRICTED,
- RevisionRecord::DELETED_RESTRICTED,
- [ 'sysop' ],
- null,
- false,
- ];
- // Bitfields match, user (oversight) does have permissions
- yield [
- RevisionRecord::DELETED_RESTRICTED,
- RevisionRecord::DELETED_RESTRICTED,
- [ 'oversight' ],
- null,
- true,
- ];
- // Check permissions using the title
- yield [
- RevisionRecord::DELETED_TEXT,
- RevisionRecord::DELETED_TEXT,
- [ 'sysop' ],
- Title::newFromText( __METHOD__ ),
- true,
- ];
- yield [
- RevisionRecord::DELETED_TEXT,
- RevisionRecord::DELETED_TEXT,
- [],
- Title::newFromText( __METHOD__ ),
- false,
- ];
- }
-
- /**
- * @dataProvider provideUserCanBitfield
- * @covers \MediaWiki\Storage\RevisionRecord::userCanBitfield
- */
- public function testUserCanBitfield( $bitField, $field, $userGroups, $title, $expected ) {
- $this->forceStandardPermissions();
-
- $user = $this->getTestUser( $userGroups )->getUser();
-
- $this->assertSame(
- $expected,
- RevisionRecord::userCanBitfield( $bitField, $field, $user, $title )
- );
- }
-
- public function provideHasSameContent() {
- /**
- * @param SlotRecord[] $slots
- * @param int $revId
- * @return RevisionStoreRecord
- */
- $recordCreator = function ( array $slots, $revId ) {
- $title = Title::newFromText( 'provideHasSameContent' );
- $title->resetArticleID( 19 );
- $slots = new RevisionSlots( $slots );
-
- return new RevisionStoreRecord(
- $title,
- new UserIdentityValue( 11, __METHOD__, 0 ),
- CommentStoreComment::newUnsavedComment( __METHOD__ ),
- (object)[
- 'rev_id' => strval( $revId ),
- 'rev_page' => strval( $title->getArticleID() ),
- 'rev_timestamp' => '20200101000000',
- 'rev_deleted' => 0,
- 'rev_minor_edit' => 0,
- 'rev_parent_id' => '5',
- 'rev_len' => $slots->computeSize(),
- 'rev_sha1' => $slots->computeSha1(),
- 'page_latest' => '18',
- ],
- $slots
- );
- };
-
- // Create some slots with content
- $mainA = SlotRecord::newUnsaved( 'main', new TextContent( 'A' ) );
- $mainB = SlotRecord::newUnsaved( 'main', new TextContent( 'B' ) );
- $auxA = SlotRecord::newUnsaved( 'aux', new TextContent( 'A' ) );
- $auxB = SlotRecord::newUnsaved( 'aux', new TextContent( 'A' ) );
-
- $initialRecord = $recordCreator( [ $mainA ], 12 );
-
- return [
- 'same record object' => [
- true,
- $initialRecord,
- $initialRecord,
- ],
- 'same record content, different object' => [
- true,
- $recordCreator( [ $mainA ], 12 ),
- $recordCreator( [ $mainA ], 13 ),
- ],
- 'same record content, aux slot, different object' => [
- true,
- $recordCreator( [ $auxA ], 12 ),
- $recordCreator( [ $auxB ], 13 ),
- ],
- 'different content' => [
- false,
- $recordCreator( [ $mainA ], 12 ),
- $recordCreator( [ $mainB ], 13 ),
- ],
- 'different content and number of slots' => [
- false,
- $recordCreator( [ $mainA ], 12 ),
- $recordCreator( [ $mainA, $mainB ], 13 ),
- ],
- ];
- }
-
- /**
- * @dataProvider provideHasSameContent
- * @covers \MediaWiki\Storage\RevisionRecord::hasSameContent
- * @group Database
- */
- public function testHasSameContent(
- $expected,
- RevisionRecord $record1,
- RevisionRecord $record2
- ) {
- $this->assertSame(
- $expected,
- $record1->hasSameContent( $record2 )
- );
- }
-
- public function provideIsDeleted() {
- yield 'no deletion' => [
- 0,
- [
- RevisionRecord::DELETED_TEXT => false,
- RevisionRecord::DELETED_COMMENT => false,
- RevisionRecord::DELETED_USER => false,
- RevisionRecord::DELETED_RESTRICTED => false,
- ]
- ];
- yield 'text deleted' => [
- RevisionRecord::DELETED_TEXT,
- [
- RevisionRecord::DELETED_TEXT => true,
- RevisionRecord::DELETED_COMMENT => false,
- RevisionRecord::DELETED_USER => false,
- RevisionRecord::DELETED_RESTRICTED => false,
- ]
- ];
- yield 'text and comment deleted' => [
- RevisionRecord::DELETED_TEXT + RevisionRecord::DELETED_COMMENT,
- [
- RevisionRecord::DELETED_TEXT => true,
- RevisionRecord::DELETED_COMMENT => true,
- RevisionRecord::DELETED_USER => false,
- RevisionRecord::DELETED_RESTRICTED => false,
- ]
- ];
- yield 'all 4 deleted' => [
- RevisionRecord::DELETED_TEXT +
- RevisionRecord::DELETED_COMMENT +
- RevisionRecord::DELETED_RESTRICTED +
- RevisionRecord::DELETED_USER,
- [
- RevisionRecord::DELETED_TEXT => true,
- RevisionRecord::DELETED_COMMENT => true,
- RevisionRecord::DELETED_USER => true,
- RevisionRecord::DELETED_RESTRICTED => true,
- ]
- ];
- }
-
- /**
- * @dataProvider provideIsDeleted
- * @covers \MediaWiki\Storage\RevisionRecord::isDeleted
- */
- public function testIsDeleted( $revDeleted, $assertionMap ) {
- $rev = $this->newRevision( [ 'rev_deleted' => $revDeleted ] );
- foreach ( $assertionMap as $deletionLevel => $expected ) {
- $this->assertSame( $expected, $rev->isDeleted( $deletionLevel ) );
- }
- }
-
}