MediaWiki  REL1_31
RevisionRecordTests.php
Go to the documentation of this file.
1 <?php
2 
4 
6 use LogicException;
14 use Title;
15 
16 // PHPCS should not complain about @covers and @dataProvider being used in traits, see T192384
17 // phpcs:disable MediaWiki.Commenting.PhpunitAnnotations.NotTestClass
18 
25 
31  protected abstract function newRevision( array $rowOverrides = [] );
32 
33  private function provideAudienceCheckData( $field ) {
34  yield 'field accessible for oversighter (ALL)' => [
36  [ 'oversight' ],
37  true,
38  false
39  ];
40 
41  yield 'field accessible for oversighter' => [
43  [ 'oversight' ],
44  true,
45  false
46  ];
47 
48  yield 'field not accessible for sysops (ALL)' => [
50  [ 'sysop' ],
51  false,
52  false
53  ];
54 
55  yield 'field not accessible for sysops' => [
57  [ 'sysop' ],
58  false,
59  false
60  ];
61 
62  yield 'field accessible for sysops' => [
63  $field,
64  [ 'sysop' ],
65  true,
66  false
67  ];
68 
69  yield 'field suppressed for logged in users' => [
70  $field,
71  [ 'user' ],
72  false,
73  false
74  ];
75 
76  yield 'unrelated field suppressed' => [
80  [ 'user' ],
81  true,
82  true
83  ];
84 
85  yield 'nothing suppressed' => [
86  0,
87  [ 'user' ],
88  true,
89  true
90  ];
91  }
92 
93  public function testSerialization_fails() {
94  $this->setExpectedException( LogicException::class );
95  $rev = $this->newRevision();
96  serialize( $rev );
97  }
98 
99  public function provideGetComment_audience() {
101  }
102 
103  private function forceStandardPermissions() {
104  $this->setMwGlobals(
105  'wgGroupPermissions',
106  [
107  'user' => [
108  'viewsuppressed' => false,
109  'suppressrevision' => false,
110  'deletedtext' => false,
111  'deletedhistory' => false,
112  ],
113  'sysop' => [
114  'viewsuppressed' => false,
115  'suppressrevision' => false,
116  'deletedtext' => true,
117  'deletedhistory' => true,
118  ],
119  'oversight' => [
120  'deletedtext' => true,
121  'deletedhistory' => true,
122  'viewsuppressed' => true,
123  'suppressrevision' => true,
124  ],
125  ]
126  );
127  }
128 
132  public function testGetComment_audience( $visibility, $groups, $userCan, $publicCan ) {
133  $this->forceStandardPermissions();
134 
135  $user = $this->getTestUser( $groups )->getUser();
136  $rev = $this->newRevision( [ 'rev_deleted' => $visibility ] );
137 
138  $this->assertNotNull( $rev->getComment( RevisionRecord::RAW ), 'raw can' );
139 
140  $this->assertSame(
141  $publicCan,
142  $rev->getComment( RevisionRecord::FOR_PUBLIC ) !== null,
143  'public can'
144  );
145  $this->assertSame(
146  $userCan,
147  $rev->getComment( RevisionRecord::FOR_THIS_USER, $user ) !== null,
148  'user can'
149  );
150  }
151 
152  public function provideGetUser_audience() {
154  }
155 
159  public function testGetUser_audience( $visibility, $groups, $userCan, $publicCan ) {
160  $this->forceStandardPermissions();
161 
162  $user = $this->getTestUser( $groups )->getUser();
163  $rev = $this->newRevision( [ 'rev_deleted' => $visibility ] );
164 
165  $this->assertNotNull( $rev->getUser( RevisionRecord::RAW ), 'raw can' );
166 
167  $this->assertSame(
168  $publicCan,
169  $rev->getUser( RevisionRecord::FOR_PUBLIC ) !== null,
170  'public can'
171  );
172  $this->assertSame(
173  $userCan,
174  $rev->getUser( RevisionRecord::FOR_THIS_USER, $user ) !== null,
175  'user can'
176  );
177  }
178 
179  public function provideGetSlot_audience() {
181  }
182 
186  public function testGetSlot_audience( $visibility, $groups, $userCan, $publicCan ) {
187  $this->forceStandardPermissions();
188 
189  $user = $this->getTestUser( $groups )->getUser();
190  $rev = $this->newRevision( [ 'rev_deleted' => $visibility ] );
191 
192  // NOTE: slot meta-data is never suppressed, just the content is!
193  $this->assertTrue( $rev->hasSlot( 'main' ), 'hasSlot is never suppressed' );
194  $this->assertNotNull( $rev->getSlot( 'main', RevisionRecord::RAW ), 'raw meta' );
195  $this->assertNotNull( $rev->getSlot( 'main', RevisionRecord::FOR_PUBLIC ), 'public meta' );
196 
197  $this->assertNotNull(
198  $rev->getSlot( 'main', RevisionRecord::FOR_THIS_USER, $user ),
199  'user can'
200  );
201 
202  try {
203  $rev->getSlot( 'main', RevisionRecord::FOR_PUBLIC )->getContent();
204  $exception = null;
205  } catch ( SuppressedDataException $ex ) {
206  $exception = $ex;
207  }
208 
209  $this->assertSame(
210  $publicCan,
211  $exception === null,
212  'public can'
213  );
214 
215  try {
216  $rev->getSlot( 'main', RevisionRecord::FOR_THIS_USER, $user )->getContent();
217  $exception = null;
218  } catch ( SuppressedDataException $ex ) {
219  $exception = $ex;
220  }
221 
222  $this->assertSame(
223  $userCan,
224  $exception === null,
225  'user can'
226  );
227  }
228 
232  public function testGetContent_audience( $visibility, $groups, $userCan, $publicCan ) {
233  $this->forceStandardPermissions();
234 
235  $user = $this->getTestUser( $groups )->getUser();
236  $rev = $this->newRevision( [ 'rev_deleted' => $visibility ] );
237 
238  $this->assertNotNull( $rev->getContent( 'main', RevisionRecord::RAW ), 'raw can' );
239 
240  $this->assertSame(
241  $publicCan,
242  $rev->getContent( 'main', RevisionRecord::FOR_PUBLIC ) !== null,
243  'public can'
244  );
245  $this->assertSame(
246  $userCan,
247  $rev->getContent( 'main', RevisionRecord::FOR_THIS_USER, $user ) !== null,
248  'user can'
249  );
250  }
251 
252  public function testGetSlot() {
253  $rev = $this->newRevision();
254 
255  $slot = $rev->getSlot( 'main' );
256  $this->assertNotNull( $slot, 'getSlot()' );
257  $this->assertSame( 'main', $slot->getRole(), 'getRole()' );
258  }
259 
260  public function testHasSlot() {
261  $rev = $this->newRevision();
262 
263  $this->assertTrue( $rev->hasSlot( 'main' ) );
264  $this->assertFalse( $rev->hasSlot( 'xyz' ) );
265  }
266 
267  public function testGetContent() {
268  $rev = $this->newRevision();
269 
270  $content = $rev->getSlot( 'main' );
271  $this->assertNotNull( $content, 'getContent()' );
272  $this->assertSame( CONTENT_MODEL_TEXT, $content->getModel(), 'getModel()' );
273  }
274 
275  public function provideUserCanBitfield() {
276  yield [ 0, 0, [], null, true ];
277  // Bitfields match, user has no permissions
278  yield [
281  [],
282  null,
283  false
284  ];
285  yield [
288  [],
289  null,
290  false,
291  ];
292  yield [
295  [],
296  null,
297  false
298  ];
299  yield [
302  [],
303  null,
304  false,
305  ];
306  // Bitfields match, user (admin) does have permissions
307  yield [
310  [ 'sysop' ],
311  null,
312  true,
313  ];
314  yield [
317  [ 'sysop' ],
318  null,
319  true,
320  ];
321  yield [
324  [ 'sysop' ],
325  null,
326  true,
327  ];
328  // Bitfields match, user (admin) does not have permissions
329  yield [
332  [ 'sysop' ],
333  null,
334  false,
335  ];
336  // Bitfields match, user (oversight) does have permissions
337  yield [
340  [ 'oversight' ],
341  null,
342  true,
343  ];
344  // Check permissions using the title
345  yield [
348  [ 'sysop' ],
349  Title::newFromText( __METHOD__ ),
350  true,
351  ];
352  yield [
355  [],
356  Title::newFromText( __METHOD__ ),
357  false,
358  ];
359  }
360 
365  public function testUserCanBitfield( $bitField, $field, $userGroups, $title, $expected ) {
366  $this->forceStandardPermissions();
367 
368  $user = $this->getTestUser( $userGroups )->getUser();
369 
370  $this->assertSame(
371  $expected,
372  RevisionRecord::userCanBitfield( $bitField, $field, $user, $title )
373  );
374  }
375 
376  public function provideHasSameContent() {
382  $recordCreator = function ( array $slots, $revId ) {
383  $title = Title::newFromText( 'provideHasSameContent' );
384  $title->resetArticleID( 19 );
385  $slots = new RevisionSlots( $slots );
386 
387  return new RevisionStoreRecord(
388  $title,
389  new UserIdentityValue( 11, __METHOD__, 0 ),
391  (object)[
392  'rev_id' => strval( $revId ),
393  'rev_page' => strval( $title->getArticleID() ),
394  'rev_timestamp' => '20200101000000',
395  'rev_deleted' => 0,
396  'rev_minor_edit' => 0,
397  'rev_parent_id' => '5',
398  'rev_len' => $slots->computeSize(),
399  'rev_sha1' => $slots->computeSha1(),
400  'page_latest' => '18',
401  ],
402  $slots
403  );
404  };
405 
406  // Create some slots with content
407  $mainA = SlotRecord::newUnsaved( 'main', new TextContent( 'A' ) );
408  $mainB = SlotRecord::newUnsaved( 'main', new TextContent( 'B' ) );
409  $auxA = SlotRecord::newUnsaved( 'aux', new TextContent( 'A' ) );
410  $auxB = SlotRecord::newUnsaved( 'aux', new TextContent( 'A' ) );
411 
412  $initialRecord = $recordCreator( [ $mainA ], 12 );
413 
414  return [
415  'same record object' => [
416  true,
417  $initialRecord,
418  $initialRecord,
419  ],
420  'same record content, different object' => [
421  true,
422  $recordCreator( [ $mainA ], 12 ),
423  $recordCreator( [ $mainA ], 13 ),
424  ],
425  'same record content, aux slot, different object' => [
426  true,
427  $recordCreator( [ $auxA ], 12 ),
428  $recordCreator( [ $auxB ], 13 ),
429  ],
430  'different content' => [
431  false,
432  $recordCreator( [ $mainA ], 12 ),
433  $recordCreator( [ $mainB ], 13 ),
434  ],
435  'different content and number of slots' => [
436  false,
437  $recordCreator( [ $mainA ], 12 ),
438  $recordCreator( [ $mainA, $mainB ], 13 ),
439  ],
440  ];
441  }
442 
448  public function testHasSameContent(
449  $expected,
450  RevisionRecord $record1,
451  RevisionRecord $record2
452  ) {
453  $this->assertSame(
454  $expected,
455  $record1->hasSameContent( $record2 )
456  );
457  }
458 
459  public function provideIsDeleted() {
460  yield 'no deletion' => [
461  0,
462  [
467  ]
468  ];
469  yield 'text deleted' => [
471  [
476  ]
477  ];
478  yield 'text and comment deleted' => [
480  [
485  ]
486  ];
487  yield 'all 4 deleted' => [
492  [
497  ]
498  ];
499  }
500 
505  public function testIsDeleted( $revDeleted, $assertionMap ) {
506  $rev = $this->newRevision( [ 'rev_deleted' => $revDeleted ] );
507  foreach ( $assertionMap as $deletionLevel => $expected ) {
508  $this->assertSame( $expected, $rev->isDeleted( $deletionLevel ) );
509  }
510  }
511 
512 }
MediaWiki\User\UserIdentityValue
Value object representing a user's identity.
Definition: UserIdentityValue.php:32
$user
please add to it if you re going to add events to the MediaWiki code where normally authentication against an external auth plugin would be creating a account $user
Definition: hooks.txt:247
MediaWiki\Tests\Storage\testHasSlot
testHasSlot()
Definition: RevisionRecordTests.php:260
CommentStoreComment\newUnsavedComment
static newUnsavedComment( $comment, array $data=null)
Create a new, unsaved CommentStoreComment.
Definition: CommentStoreComment.php:65
Title\newFromText
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:273
MediaWiki\Tests\Storage\testGetSlot
testGetSlot()
Definition: RevisionRecordTests.php:252
MediaWiki\Tests\Storage\testGetContent
testGetContent()
Definition: RevisionRecordTests.php:267
use
Apache License January AND DISTRIBUTION Definitions License shall mean the terms and conditions for use
Definition: APACHE-LICENSE-2.0.txt:10
array
the array() calling protocol came about after MediaWiki 1.4rc1.
MediaWiki\Tests\Storage\testGetSlot_audience
testGetSlot_audience( $visibility, $groups, $userCan, $publicCan)
provideGetSlot_audience
Definition: RevisionRecordTests.php:186
MediaWiki\Storage\SuppressedDataException
Exception raised in response to an audience check when attempting to access suppressed information wi...
Definition: SuppressedDataException.php:31
MediaWiki\Tests\Storage\provideGetUser_audience
provideGetUser_audience()
Definition: RevisionRecordTests.php:152
serialize
serialize()
Definition: ApiMessage.php:184
MediaWiki\Tests\Storage\provideAudienceCheckData
provideAudienceCheckData( $field)
Definition: RevisionRecordTests.php:33
MediaWiki\Storage\RevisionSlots
Value object representing the set of slots belonging to a revision.
Definition: RevisionSlots.php:34
true
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses just before the function returns a value If you return true
Definition: hooks.txt:2006
php
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
Definition: injection.txt:37
MediaWiki\Tests\Storage\testSerialization_fails
testSerialization_fails()
Definition: RevisionRecordTests.php:93
MediaWiki\Storage\RevisionRecord\hasSameContent
hasSameContent(RevisionRecord $rec)
Definition: RevisionRecord.php:125
MediaWiki\Storage\RevisionRecord\FOR_PUBLIC
const FOR_PUBLIC
Definition: RevisionRecord.php:55
MediaWiki\Tests\Storage
Definition: BlobStoreFactoryTest.php:3
MediaWiki\Tests\Storage\testUserCanBitfield
testUserCanBitfield( $bitField, $field, $userGroups, $title, $expected)
provideUserCanBitfield \MediaWiki\Storage\RevisionRecord::userCanBitfield
Definition: RevisionRecordTests.php:365
MediaWiki\Storage\RevisionStoreRecord
A RevisionRecord representing an existing revision persisted in the revision table.
Definition: RevisionStoreRecord.php:38
MediaWiki\Storage\SlotRecord\newUnsaved
static newUnsaved( $role, Content $content)
Constructs a new Slot from a Content object for a new revision.
Definition: SlotRecord.php:124
MediaWiki\Tests\Storage\testGetUser_audience
testGetUser_audience( $visibility, $groups, $userCan, $publicCan)
provideGetUser_audience
Definition: RevisionRecordTests.php:159
MediaWiki\Tests\Storage\provideGetComment_audience
provideGetComment_audience()
Definition: RevisionRecordTests.php:99
$title
namespace and then decline to actually register it file or subcat img or subcat $title
Definition: hooks.txt:964
MediaWiki\Storage\RevisionRecord
Page revision base class.
Definition: RevisionRecord.php:44
MediaWiki\Tests\Storage\testGetComment_audience
testGetComment_audience( $visibility, $groups, $userCan, $publicCan)
provideGetComment_audience
Definition: RevisionRecordTests.php:132
MediaWiki\Storage\RevisionRecord\RAW
const RAW
Definition: RevisionRecord.php:57
MediaWiki\Storage\RevisionRecord\DELETED_RESTRICTED
const DELETED_RESTRICTED
Definition: RevisionRecord.php:50
MediaWiki\Tests\Storage\provideUserCanBitfield
provideUserCanBitfield()
Definition: RevisionRecordTests.php:275
MediaWiki\Tests\Storage\testHasSameContent
testHasSameContent( $expected, RevisionRecord $record1, RevisionRecord $record2)
provideHasSameContent \MediaWiki\Storage\RevisionRecord::hasSameContent Database
Definition: RevisionRecordTests.php:448
MediaWiki\Tests\Storage\provideHasSameContent
provideHasSameContent()
Definition: RevisionRecordTests.php:376
TextContent
Content object implementation for representing flat text.
Definition: TextContent.php:35
MediaWiki\Storage\RevisionRecord\DELETED_COMMENT
const DELETED_COMMENT
Definition: RevisionRecord.php:48
$rev
presenting them properly to the user as errors is done by the caller return true use this to change the list i e etc $rev
Definition: hooks.txt:1777
Title
Represents a title within MediaWiki.
Definition: Title.php:39
MediaWiki\Tests\Storage\testIsDeleted
testIsDeleted( $revDeleted, $assertionMap)
provideIsDeleted \MediaWiki\Storage\RevisionRecord::isDeleted
Definition: RevisionRecordTests.php:505
MediaWiki\Tests\Storage\testGetContent_audience
testGetContent_audience( $visibility, $groups, $userCan, $publicCan)
provideGetSlot_audience
Definition: RevisionRecordTests.php:232
MediaWiki\Storage\SlotRecord
Value object representing a content slot associated with a page revision.
Definition: SlotRecord.php:38
MediaWiki\Storage\RevisionRecord\DELETED_USER
const DELETED_USER
Definition: RevisionRecord.php:49
as
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
Definition: distributors.txt:22
MediaWiki\Storage\RevisionRecord\DELETED_TEXT
const DELETED_TEXT
Definition: RevisionRecord.php:47
MediaWiki\Tests\Storage\RevisionRecordTests
trait RevisionRecordTests
\MediaWiki\Storage\RevisionRecord
Definition: RevisionRecordTests.php:24
MediaWiki\Tests\Storage\provideGetSlot_audience
provideGetSlot_audience()
Definition: RevisionRecordTests.php:179
MediaWiki\Storage\RevisionRecord\SUPPRESSED_ALL
const SUPPRESSED_ALL
Definition: RevisionRecord.php:52
class
you have access to all of the normal MediaWiki so you can get a DB use the etc For full docs on the Maintenance class
Definition: maintenance.txt:56
MediaWiki\Tests\Storage\provideIsDeleted
provideIsDeleted()
Definition: RevisionRecordTests.php:459
CONTENT_MODEL_TEXT
const CONTENT_MODEL_TEXT
Definition: Defines.php:248
MediaWiki\Storage\RevisionRecord\userCanBitfield
static userCanBitfield( $bitfield, $field, User $user, Title $title=null)
Determine if the current user is allowed to view a particular field of this revision,...
Definition: RevisionRecord.php:464
false
processing should stop and the error should be shown to the user * false
Definition: hooks.txt:187
CommentStoreComment
CommentStoreComment represents a comment stored by CommentStore.
Definition: CommentStoreComment.php:28
MediaWiki\Storage\RevisionRecord\FOR_THIS_USER
const FOR_THIS_USER
Definition: RevisionRecord.php:56
MediaWiki\Tests\Storage\forceStandardPermissions
forceStandardPermissions()
Definition: RevisionRecordTests.php:103