MediaWiki  1.31.0
RevisionRecord.php
Go to the documentation of this file.
1 <?php
23 namespace MediaWiki\Storage;
24 
26 use Content;
27 use InvalidArgumentException;
28 use LogicException;
32 use Title;
33 use User;
34 use Wikimedia\Assert\Assert;
35 
44 abstract class RevisionRecord {
45 
46  // RevisionRecord deletion constants
47  const DELETED_TEXT = 1;
48  const DELETED_COMMENT = 2;
49  const DELETED_USER = 4;
50  const DELETED_RESTRICTED = 8;
51  const SUPPRESSED_USER = 12; // convenience
52  const SUPPRESSED_ALL = 15; // convenience
53 
54  // Audience options for accessors
55  const FOR_PUBLIC = 1;
56  const FOR_THIS_USER = 2;
57  const RAW = 3;
58 
60  protected $mWiki = false;
62  protected $mId;
64  protected $mPageId;
66  protected $mUser;
68  protected $mMinorEdit = false;
70  protected $mTimestamp;
72  protected $mDeleted = 0;
74  protected $mSize;
76  protected $mSha1;
78  protected $mParentId;
80  protected $mComment;
81 
83  protected $mTitle; // TODO: we only need the title for permission checks!
84 
86  protected $mSlots;
87 
99  function __construct( Title $title, RevisionSlots $slots, $wikiId = false ) {
100  Assert::parameterType( 'string|boolean', $wikiId, '$wikiId' );
101 
102  $this->mTitle = $title;
103  $this->mSlots = $slots;
104  $this->mWiki = $wikiId;
105 
106  // XXX: this is a sensible default, but we may not have a Title object here in the future.
107  $this->mPageId = $title->getArticleID();
108  }
109 
115  public function __sleep() {
116  throw new LogicException( __CLASS__ . ' is not serializable.' );
117  }
118 
125  public function hasSameContent( RevisionRecord $rec ) {
126  if ( $rec === $this ) {
127  return true;
128  }
129 
130  if ( $this->getId() !== null && $this->getId() === $rec->getId() ) {
131  return true;
132  }
133 
134  // check size before hash, since size is quicker to compute
135  if ( $this->getSize() !== $rec->getSize() ) {
136  return false;
137  }
138 
139  // instead of checking the hash, we could also check the content addresses of all slots.
140 
141  if ( $this->getSha1() === $rec->getSha1() ) {
142  return true;
143  }
144 
145  return false;
146  }
147 
165  public function getContent( $role, $audience = self::FOR_PUBLIC, User $user = null ) {
166  // XXX: throwing an exception would be nicer, but would a further
167  // departure from the signature of Revision::getContent(), and thus
168  // more complex and error prone refactoring.
169  if ( !$this->audienceCan( self::DELETED_TEXT, $audience, $user ) ) {
170  return null;
171  }
172 
173  $content = $this->getSlot( $role, $audience, $user )->getContent();
174  return $content->copy();
175  }
176 
189  public function getSlot( $role, $audience = self::FOR_PUBLIC, User $user = null ) {
190  $slot = $this->mSlots->getSlot( $role );
191 
192  if ( !$this->audienceCan( self::DELETED_TEXT, $audience, $user ) ) {
193  return SlotRecord::newWithSuppressedContent( $slot );
194  }
195 
196  return $slot;
197  }
198 
206  public function hasSlot( $role ) {
207  return $this->mSlots->hasSlot( $role );
208  }
209 
216  public function getSlotRoles() {
217  return $this->mSlots->getSlotRoles();
218  }
219 
229  public function getId() {
230  return $this->mId;
231  }
232 
245  public function getParentId() {
246  return $this->mParentId;
247  }
248 
259  abstract public function getSize();
260 
272  abstract public function getSha1();
273 
281  public function getPageId() {
282  return $this->mPageId;
283  }
284 
290  public function getWikiId() {
291  return $this->mWiki;
292  }
293 
301  public function getPageAsLinkTarget() {
302  return $this->mTitle;
303  }
304 
321  public function getUser( $audience = self::FOR_PUBLIC, User $user = null ) {
322  if ( !$this->audienceCan( self::DELETED_USER, $audience, $user ) ) {
323  return null;
324  } else {
325  return $this->mUser;
326  }
327  }
328 
346  public function getComment( $audience = self::FOR_PUBLIC, User $user = null ) {
347  if ( !$this->audienceCan( self::DELETED_COMMENT, $audience, $user ) ) {
348  return null;
349  } else {
350  return $this->mComment;
351  }
352  }
353 
359  public function isMinor() {
360  return (bool)$this->mMinorEdit;
361  }
362 
370  public function isDeleted( $field ) {
371  return ( $this->getVisibility() & $field ) == $field;
372  }
373 
381  public function getVisibility() {
382  return (int)$this->mDeleted;
383  }
384 
392  public function getTimestamp() {
393  return $this->mTimestamp;
394  }
395 
413  protected function audienceCan( $field, $audience, User $user = null ) {
414  if ( $audience == self::FOR_PUBLIC && $this->isDeleted( $field ) ) {
415  return false;
416  } elseif ( $audience == self::FOR_THIS_USER ) {
417  if ( !$user ) {
418  throw new InvalidArgumentException(
419  'A User object must be given when checking FOR_THIS_USER audience.'
420  );
421  }
422 
423  if ( !$this->userCan( $field, $user ) ) {
424  return false;
425  }
426  }
427 
428  return true;
429  }
430 
443  protected function userCan( $field, User $user ) {
444  // TODO: use callback for permission checks, so we don't need to know a Title object!
445  return self::userCanBitfield( $this->getVisibility(), $field, $user, $this->mTitle );
446  }
447 
464  public static function userCanBitfield( $bitfield, $field, User $user, Title $title = null ) {
465  if ( $bitfield & $field ) { // aspect is deleted
466  if ( $bitfield & self::DELETED_RESTRICTED ) {
467  $permissions = [ 'suppressrevision', 'viewsuppressed' ];
468  } elseif ( $field & self::DELETED_TEXT ) {
469  $permissions = [ 'deletedtext' ];
470  } else {
471  $permissions = [ 'deletedhistory' ];
472  }
473  $permissionlist = implode( ', ', $permissions );
474  if ( $title === null ) {
475  wfDebug( "Checking for $permissionlist due to $field match on $bitfield\n" );
476  return call_user_func_array( [ $user, 'isAllowedAny' ], $permissions );
477  } else {
478  $text = $title->getPrefixedText();
479  wfDebug( "Checking for $permissionlist on $text due to $field match on $bitfield\n" );
480  foreach ( $permissions as $perm ) {
481  if ( $title->userCan( $perm, $user ) ) {
482  return true;
483  }
484  }
485  return false;
486  }
487  } else {
488  return true;
489  }
490  }
491 
492 }
MediaWiki\Storage\RevisionRecord\$mId
int null $mId
Definition: RevisionRecord.php:62
MediaWiki\Storage\RevisionRecord\hasSlot
hasSlot( $role)
Returns whether the given slot is defined in this revision.
Definition: RevisionRecord.php:206
$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:244
MediaWiki\Storage\RevisionRecord\getVisibility
getVisibility()
Get the deletion bitfield of the revision.
Definition: RevisionRecord.php:381
MediaWiki\Storage\RevisionRecord\getSlot
getSlot( $role, $audience=self::FOR_PUBLIC, User $user=null)
Returns meta-data for the given slot.
Definition: RevisionRecord.php:189
MediaWiki\Storage\RevisionRecord\$mSlots
RevisionSlots $mSlots
Definition: RevisionRecord.php:86
MediaWiki\Storage\RevisionRecord\$mSha1
string null $mSha1
Definition: RevisionRecord.php:76
MediaWiki\Storage\RevisionRecord\$mTimestamp
string null $mTimestamp
Definition: RevisionRecord.php:70
MediaWiki\Storage\RevisionRecord\$mMinorEdit
bool $mMinorEdit
Definition: RevisionRecord.php:68
use
as see the revision history and available at free of to any person obtaining a copy of this software and associated documentation to deal in the Software without including without limitation the rights to use
Definition: MIT-LICENSE.txt:10
MediaWiki\Storage\RevisionRecord\getWikiId
getWikiId()
Get the ID of the wiki this revision belongs to.
Definition: RevisionRecord.php:290
MediaWiki\Storage\RevisionRecord\userCan
userCan( $field, User $user)
Determine if the current user is allowed to view a particular field of this revision,...
Definition: RevisionRecord.php:443
User
User
Definition: All_system_messages.txt:425
MediaWiki\Storage\RevisionSlots
Value object representing the set of slots belonging to a revision.
Definition: RevisionSlots.php:34
MediaWiki\User\UserIdentity
Interface for objects representing user identity.
Definition: UserIdentity.php:32
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:35
MediaWiki\Storage\RevisionRecord\hasSameContent
hasSameContent(RevisionRecord $rec)
Definition: RevisionRecord.php:125
MediaWiki\Storage\RevisionRecord\$mDeleted
int $mDeleted
using the DELETED_XXX and SUPPRESSED_XXX flags
Definition: RevisionRecord.php:72
MediaWiki\Storage\RevisionRecord\FOR_PUBLIC
const FOR_PUBLIC
Definition: RevisionRecord.php:55
MediaWiki\Storage\RevisionRecord\$mPageId
int null $mPageId
Definition: RevisionRecord.php:64
MediaWiki\Storage\RevisionRecord\getComment
getComment( $audience=self::FOR_PUBLIC, User $user=null)
Fetch revision comment, if it's available to the specified audience.
Definition: RevisionRecord.php:346
MediaWiki\Storage\RevisionRecord\getUser
getUser( $audience=self::FOR_PUBLIC, User $user=null)
Fetch revision's author's user identity, if it's available to the specified audience.
Definition: RevisionRecord.php:321
MWException
MediaWiki exception.
Definition: MWException.php:26
MediaWiki\Storage\RevisionRecord\getSlotRoles
getSlotRoles()
Returns the slot names (roles) of all slots present in this revision.
Definition: RevisionRecord.php:216
$title
namespace and then decline to actually register it file or subcat img or subcat $title
Definition: hooks.txt:934
MediaWiki\Storage\RevisionRecord\getSha1
getSha1()
Returns the base36 sha1 of this revision.
MediaWiki\Storage\RevisionRecord\SUPPRESSED_USER
const SUPPRESSED_USER
Definition: RevisionRecord.php:51
MediaWiki\Storage\RevisionRecord\$mParentId
int null $mParentId
Definition: RevisionRecord.php:78
MediaWiki\Storage\RevisionRecord\$mComment
CommentStoreComment null $mComment
Definition: RevisionRecord.php:80
MediaWiki\Storage\RevisionRecord\__sleep
__sleep()
Implemented to defy serialization.
Definition: RevisionRecord.php:115
MediaWiki\Storage\RevisionRecord\getParentId
getParentId()
Get parent revision ID (the original previous page revision).
Definition: RevisionRecord.php:245
wfDebug
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
Definition: GlobalFunctions.php:982
MediaWiki\Storage\RevisionRecord
Page revision base class.
Definition: RevisionRecord.php:44
MediaWiki\Storage\RevisionRecord\$mWiki
string $mWiki
Wiki ID; false means the current wiki.
Definition: RevisionRecord.php:60
MediaWiki\Storage\RevisionRecord\getPageAsLinkTarget
getPageAsLinkTarget()
Returns the title of the page this revision is associated with as a LinkTarget object.
Definition: RevisionRecord.php:301
MediaWiki\Storage\RevisionRecord\RAW
const RAW
Definition: RevisionRecord.php:57
MediaWiki\Storage\RevisionRecord\$mTitle
Title $mTitle
Definition: RevisionRecord.php:83
MediaWiki\Storage\RevisionRecord\$mSize
int null $mSize
Definition: RevisionRecord.php:74
MediaWiki\Storage\RevisionRecord\$mUser
UserIdentity null $mUser
Definition: RevisionRecord.php:66
MediaWiki\Storage\RevisionRecord\DELETED_RESTRICTED
const DELETED_RESTRICTED
Definition: RevisionRecord.php:50
MediaWiki\Storage
Definition: BlobAccessException.php:23
MediaWiki\Storage\RevisionRecord\DELETED_COMMENT
const DELETED_COMMENT
Definition: RevisionRecord.php:48
Content
Base interface for content objects.
Definition: Content.php:34
MediaWiki\Storage\RevisionRecord\getSize
getSize()
Returns the nominal size of this revision, in bogo-bytes.
Title
Represents a title within MediaWiki.
Definition: Title.php:39
MediaWiki\Storage\SlotRecord\newWithSuppressedContent
static newWithSuppressedContent(SlotRecord $slot)
Returns a new SlotRecord just like the given $slot, except that calling getContent() will fail with a...
Definition: SlotRecord.php:58
MediaWiki\Storage\RevisionRecord\__construct
__construct(Title $title, RevisionSlots $slots, $wikiId=false)
Definition: RevisionRecord.php:99
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:9
MediaWiki\Storage\RevisionRecord\getTimestamp
getTimestamp()
MCR migration note: this replaces Revision::getTimestamp.
Definition: RevisionRecord.php:392
MediaWiki\Storage\RevisionRecord\DELETED_TEXT
const DELETED_TEXT
Definition: RevisionRecord.php:47
MediaWiki\Storage\RevisionRecord\audienceCan
audienceCan( $field, $audience, User $user=null)
Check that the given audience has access to the given field.
Definition: RevisionRecord.php:413
MediaWiki\Storage\RevisionRecord\isDeleted
isDeleted( $field)
MCR migration note: this replaces Revision::isDeleted.
Definition: RevisionRecord.php:370
MediaWiki\Storage\RevisionRecord\SUPPRESSED_ALL
const SUPPRESSED_ALL
Definition: RevisionRecord.php:52
MediaWiki\Storage\RevisionRecord\getId
getId()
Get revision ID.
Definition: RevisionRecord.php:229
MediaWiki\Linker\LinkTarget
Definition: LinkTarget.php:26
User
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:53
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
MediaWiki\Storage\RevisionRecord\getContent
getContent( $role, $audience=self::FOR_PUBLIC, User $user=null)
Returns the Content of the given slot of this revision.
Definition: RevisionRecord.php:165
CommentStoreComment
CommentStoreComment represents a comment stored by CommentStore.
Definition: CommentStoreComment.php:28
MediaWiki\Storage\RevisionRecord\isMinor
isMinor()
MCR migration note: this replaces Revision::isMinor.
Definition: RevisionRecord.php:359
MediaWiki\Storage\RevisionRecord\FOR_THIS_USER
const FOR_THIS_USER
Definition: RevisionRecord.php:56
MediaWiki\Storage\RevisionRecord\getPageId
getPageId()
Get the page ID.
Definition: RevisionRecord.php:281