MediaWiki  master
RevisionSlots.php
Go to the documentation of this file.
1 <?php
23 namespace MediaWiki\Revision;
24 
25 use Content;
26 use Wikimedia\Assert\Assert;
27 use Wikimedia\NonSerializable\NonSerializableTrait;
28 
42  use NonSerializableTrait;
43 
45  protected $slots;
46 
53  public function __construct( $slots ) {
54  Assert::parameterType( 'array|callable', $slots, '$slots' );
55 
56  if ( is_callable( $slots ) ) {
57  $this->slots = $slots;
58  } else {
59  $this->setSlotsInternal( $slots );
60  }
61  }
62 
66  private function setSlotsInternal( array $slots ): void {
67  Assert::parameterElementType( SlotRecord::class, $slots, '$slots' );
68 
69  $this->slots = [];
70 
71  // re-key the slot array
72  foreach ( $slots as $slot ) {
73  $role = $slot->getRole();
74  $this->slots[$role] = $slot;
75  }
76  }
77 
93  public function getContent( $role ): Content {
94  // Return a copy to be safe. Immutable content objects return $this from copy().
95  return $this->getSlot( $role )->getContent()->copy();
96  }
97 
108  public function getSlot( $role ): SlotRecord {
109  $slots = $this->getSlots();
110 
111  if ( isset( $slots[$role] ) ) {
112  return $slots[$role];
113  } else {
114  throw new RevisionAccessException(
115  'No such slot: {role}',
116  [ 'role' => $role ]
117  );
118  }
119  }
120 
128  public function hasSlot( $role ): bool {
129  $slots = $this->getSlots();
130 
131  return isset( $slots[$role] );
132  }
133 
140  public function getSlotRoles(): array {
141  $slots = $this->getSlots();
142  return array_keys( $slots );
143  }
144 
153  public function computeSize(): int {
154  return array_reduce( $this->getPrimarySlots(), static function ( $accu, SlotRecord $slot ) {
155  return $accu + $slot->getSize();
156  }, 0 );
157  }
158 
168  public function getSlots(): array {
169  if ( is_callable( $this->slots ) ) {
170  $slots = call_user_func( $this->slots );
171 
172  Assert::postcondition(
173  is_array( $slots ),
174  'Slots info callback should return an array of objects'
175  );
176 
177  $this->setSlotsInternal( $slots );
178  }
179 
180  return $this->slots;
181  }
182 
195  public function computeSha1(): string {
196  $slots = $this->getPrimarySlots();
197  ksort( $slots );
198 
199  if ( empty( $slots ) ) {
200  return SlotRecord::base36Sha1( '' );
201  }
202 
203  return array_reduce( $slots, static function ( $accu, SlotRecord $slot ) {
204  return $accu === null
205  ? $slot->getSha1()
206  : SlotRecord::base36Sha1( $accu . $slot->getSha1() );
207  }, null );
208  }
209 
218  public function getOriginalSlots(): array {
219  return array_filter(
220  $this->getSlots(),
221  static function ( SlotRecord $slot ) {
222  return !$slot->isInherited();
223  }
224  );
225  }
226 
235  public function getInheritedSlots(): array {
236  return array_filter(
237  $this->getSlots(),
238  static function ( SlotRecord $slot ) {
239  return $slot->isInherited();
240  }
241  );
242  }
243 
250  public function getPrimarySlots(): array {
251  return array_filter(
252  $this->getSlots(),
253  static function ( SlotRecord $slot ) {
254  return !$slot->isDerived();
255  }
256  );
257  }
258 
268  public function hasSameContent( RevisionSlots $other ): bool {
269  if ( $other === $this ) {
270  return true;
271  }
272 
273  $aSlots = $this->getSlots();
274  $bSlots = $other->getSlots();
275 
276  ksort( $aSlots );
277  ksort( $bSlots );
278 
279  if ( array_keys( $aSlots ) !== array_keys( $bSlots ) ) {
280  return false;
281  }
282 
283  foreach ( $aSlots as $role => $s ) {
284  $t = $bSlots[$role];
285 
286  if ( !$s->hasSameContent( $t ) ) {
287  return false;
288  }
289  }
290 
291  return true;
292  }
293 
303  public function getRolesWithDifferentContent( RevisionSlots $other ): array {
304  if ( $other === $this ) {
305  return [];
306  }
307 
308  $aSlots = $this->getSlots();
309  $bSlots = $other->getSlots();
310 
311  ksort( $aSlots );
312  ksort( $bSlots );
313 
314  $different = array_keys( array_merge(
315  array_diff_key( $aSlots, $bSlots ),
316  array_diff_key( $bSlots, $aSlots )
317  ) );
318 
320  $common = array_intersect_key( $aSlots, $bSlots );
321 
322  foreach ( $common as $role => $s ) {
323  $t = $bSlots[$role];
324 
325  if ( !$s->hasSameContent( $t ) ) {
326  $different[] = $role;
327  }
328  }
329 
330  return $different;
331  }
332 
333 }
334 
339 class_alias( RevisionSlots::class, 'MediaWiki\Storage\RevisionSlots' );
MediaWiki\Revision\RevisionAccessException
Exception representing a failure to look up a revision.
Definition: RevisionAccessException.php:37
MediaWiki\Revision\RevisionSlots\getSlots
getSlots()
Returns an associative array that maps role names to SlotRecords.
Definition: RevisionSlots.php:168
MediaWiki\Revision\RevisionSlots\getPrimarySlots
getPrimarySlots()
Return all primary slots (those that are not derived).
Definition: RevisionSlots.php:250
MediaWiki\Revision\RevisionSlots\hasSlot
hasSlot( $role)
Returns whether the given slot is set.
Definition: RevisionSlots.php:128
MediaWiki\Revision\RevisionSlots\getRolesWithDifferentContent
getRolesWithDifferentContent(RevisionSlots $other)
Find roles for which the $other RevisionSlots object has different content as this RevisionSlots obje...
Definition: RevisionSlots.php:303
MediaWiki\Revision\RevisionSlots\$slots
SlotRecord[] callable $slots
Definition: RevisionSlots.php:45
MediaWiki\Revision\SlotRecord\getSha1
getSha1()
Returns the content size.
Definition: SlotRecord.php:556
MediaWiki\Revision\RevisionSlots\setSlotsInternal
setSlotsInternal(array $slots)
Definition: RevisionSlots.php:66
MediaWiki\Revision
Definition: ContributionsLookup.php:3
MediaWiki\Revision\RevisionSlots\getSlotRoles
getSlotRoles()
Returns the slot names (roles) of all slots present in this revision.
Definition: RevisionSlots.php:140
MediaWiki\Revision\RevisionSlots\computeSha1
computeSha1()
Computes the combined hash of the revisions's slots.
Definition: RevisionSlots.php:195
$s
foreach( $mmfl['setupFiles'] as $fileName) if( $queue) if(empty( $mmfl['quiet'])) $s
Definition: mergeMessageFileList.php:206
MediaWiki\Revision\RevisionSlots\getOriginalSlots
getOriginalSlots()
Return all slots that belong to the revision they originate from (that is, they are not inherited fro...
Definition: RevisionSlots.php:218
MediaWiki\Revision\SlotRecord\isInherited
isInherited()
Whether this slot was inherited from an older revision.
Definition: SlotRecord.php:438
MediaWiki\Revision\RevisionSlots\__construct
__construct( $slots)
Definition: RevisionSlots.php:53
Content
Base interface for content objects.
Definition: Content.php:35
MediaWiki\Revision\SlotRecord\getSize
getSize()
Returns the content size.
Definition: SlotRecord.php:540
MediaWiki\Revision\SlotRecord\isDerived
isDerived()
Definition: SlotRecord.php:684
MediaWiki\Revision\SlotRecord\base36Sha1
static base36Sha1( $blob)
Get the base 36 SHA-1 value for a string of text.
Definition: SlotRecord.php:630
MediaWiki\Revision\RevisionSlots\computeSize
computeSize()
Computes the total nominal size of the revision's slots, in bogo-bytes.
Definition: RevisionSlots.php:153
MediaWiki\Revision\RevisionSlots
Value object representing the set of slots belonging to a revision.
Definition: RevisionSlots.php:41
MediaWiki\Revision\RevisionSlots\getContent
getContent( $role)
Returns the Content of the given slot.
Definition: RevisionSlots.php:93
MediaWiki\Revision\RevisionSlots\getSlot
getSlot( $role)
Returns the SlotRecord of the given slot.
Definition: RevisionSlots.php:108
$t
$t
Definition: testCompression.php:74
MediaWiki\Revision\RevisionSlots\getInheritedSlots
getInheritedSlots()
Return all slots that are not originate in the revision they belong to (that is, they are inherited f...
Definition: RevisionSlots.php:235
MediaWiki\Revision\RevisionSlots\hasSameContent
hasSameContent(RevisionSlots $other)
Checks whether the other RevisionSlots instance has the same content as this instance.
Definition: RevisionSlots.php:268
MediaWiki\Revision\SlotRecord
Value object representing a content slot associated with a page revision.
Definition: SlotRecord.php:40