MediaWiki  master
DatabaseBlock.php
Go to the documentation of this file.
1 <?php
23 namespace MediaWiki\Block;
24 
25 use ActorMigration;
26 use CommentStore;
27 use Hooks;
28 use Html;
34 use MWException;
35 use stdClass;
36 use Title;
37 use User;
38 use Wikimedia\IPUtils;
41 
55  public $mAuto;
56 
62 
64  private $mId;
65 
67  private $mFromMaster;
68 
70  private $forcedTargetID;
71 
73  private $isAutoblocking;
74 
76  private $restrictions;
77 
79  private $blocker;
80 
101  public function __construct( array $options = [] ) {
102  parent::__construct( $options );
103 
104  $defaults = [
105  'user' => null,
106  'auto' => false,
107  'expiry' => '',
108  'createAccount' => false,
109  'enableAutoblock' => false,
110  'blockEmail' => false,
111  'allowUsertalk' => false,
112  'sitewide' => true,
113  'by' => null,
114  'byText' => '',
115  ];
116 
117  $options += $defaults;
118 
119  if ( $this->target instanceof User && $options['user'] ) {
120  # Needed for foreign users
121  $this->forcedTargetID = $options['user'];
122  }
123 
124  if ( $options['by'] ) {
125  # Local user
126  $this->setBlocker( User::newFromId( $options['by'] ) );
127  } else {
128  # Foreign user
129  $this->setBlocker( $options['byText'] );
130  }
131 
132  $this->setExpiry( wfGetDB( DB_REPLICA )->decodeExpiry( $options['expiry'] ) );
133 
134  # Boolean settings
135  $this->mAuto = (bool)$options['auto'];
136  $this->isAutoblocking( (bool)$options['enableAutoblock'] );
137  $this->isSitewide( (bool)$options['sitewide'] );
138  $this->isEmailBlocked( (bool)$options['blockEmail'] );
139  $this->isCreateAccountBlocked( (bool)$options['createAccount'] );
140  $this->isUsertalkEditAllowed( (bool)$options['allowUsertalk'] );
141 
142  $this->mFromMaster = false;
143  }
144 
151  public static function newFromID( $id ) {
152  $dbr = wfGetDB( DB_REPLICA );
153  $blockQuery = self::getQueryInfo();
154  $res = $dbr->selectRow(
155  $blockQuery['tables'],
156  $blockQuery['fields'],
157  [ 'ipb_id' => $id ],
158  __METHOD__,
159  [],
160  $blockQuery['joins']
161  );
162  if ( $res ) {
163  return self::newFromRow( $res );
164  } else {
165  return null;
166  }
167  }
168 
178  public static function getQueryInfo() {
179  $commentQuery = CommentStore::getStore()->getJoin( 'ipb_reason' );
180  $actorQuery = ActorMigration::newMigration()->getJoin( 'ipb_by' );
181  return [
182  'tables' => [ 'ipblocks' ] + $commentQuery['tables'] + $actorQuery['tables'],
183  'fields' => [
184  'ipb_id',
185  'ipb_address',
186  'ipb_timestamp',
187  'ipb_auto',
188  'ipb_anon_only',
189  'ipb_create_account',
190  'ipb_enable_autoblock',
191  'ipb_expiry',
192  'ipb_deleted',
193  'ipb_block_email',
194  'ipb_allow_usertalk',
195  'ipb_parent_block_id',
196  'ipb_sitewide',
197  ] + $commentQuery['fields'] + $actorQuery['fields'],
198  'joins' => $commentQuery['joins'] + $actorQuery['joins'],
199  ];
200  }
201 
209  public function equals( DatabaseBlock $block ) {
210  return (
211  (string)$this->target == (string)$block->target
212  && $this->type == $block->type
213  && $this->mAuto == $block->mAuto
214  && $this->isHardblock() == $block->isHardblock()
215  && $this->isCreateAccountBlocked() == $block->isCreateAccountBlocked()
216  && $this->getExpiry() == $block->getExpiry()
217  && $this->isAutoblocking() == $block->isAutoblocking()
218  && $this->getHideName() == $block->getHideName()
219  && $this->isEmailBlocked() == $block->isEmailBlocked()
220  && $this->isUsertalkEditAllowed() == $block->isUsertalkEditAllowed()
221  && $this->getReasonComment()->text == $block->getReasonComment()->text
222  && $this->isSitewide() == $block->isSitewide()
223  // DatabaseBlock::getRestrictions() may perform a database query, so
224  // keep it at the end.
225  && $this->getBlockRestrictionStore()->equals(
226  $this->getRestrictions(), $block->getRestrictions()
227  )
228  );
229  }
230 
243  protected static function newLoad(
244  $specificTarget,
245  $specificType,
246  $fromMaster,
247  $vagueTarget = null
248  ) {
249  $db = wfGetDB( $fromMaster ? DB_MASTER : DB_REPLICA );
250 
251  if ( $specificType !== null ) {
252  $conds = [ 'ipb_address' => [ (string)$specificTarget ] ];
253  } else {
254  $conds = [ 'ipb_address' => [] ];
255  }
256 
257  # Be aware that the != '' check is explicit, since empty values will be
258  # passed by some callers (T31116)
259  if ( $vagueTarget != '' ) {
260  list( $target, $type ) = self::parseTarget( $vagueTarget );
261  switch ( $type ) {
262  case self::TYPE_USER:
263  # Slightly weird, but who are we to argue?
264  $conds['ipb_address'][] = (string)$target;
265  break;
266 
267  case self::TYPE_IP:
268  $conds['ipb_address'][] = (string)$target;
269  $conds['ipb_address'] = array_unique( $conds['ipb_address'] );
270  $conds[] = self::getRangeCond( IPUtils::toHex( $target ) );
271  $conds = $db->makeList( $conds, LIST_OR );
272  break;
273 
274  case self::TYPE_RANGE:
275  list( $start, $end ) = IPUtils::parseRange( $target );
276  $conds['ipb_address'][] = (string)$target;
277  $conds[] = self::getRangeCond( $start, $end );
278  $conds = $db->makeList( $conds, LIST_OR );
279  break;
280 
281  default:
282  throw new MWException( "Tried to load block with invalid type" );
283  }
284  }
285 
286  $blockQuery = self::getQueryInfo();
287  $res = $db->select(
288  $blockQuery['tables'],
289  $blockQuery['fields'],
290  $conds,
291  __METHOD__,
292  [],
293  $blockQuery['joins']
294  );
295 
296  $blocks = [];
297  $blockIds = [];
298  $autoBlocks = [];
299  foreach ( $res as $row ) {
300  $block = self::newFromRow( $row );
301 
302  # Don't use expired blocks
303  if ( $block->isExpired() ) {
304  continue;
305  }
306 
307  # Don't use anon only blocks on users
308  if ( $specificType == self::TYPE_USER && !$block->isHardblock() ) {
309  continue;
310  }
311 
312  // Check for duplicate autoblocks
313  if ( $block->getType() === self::TYPE_AUTO ) {
314  $autoBlocks[] = $block;
315  } else {
316  $blocks[] = $block;
317  $blockIds[] = $block->getId();
318  }
319  }
320 
321  // Only add autoblocks that aren't duplicates
322  foreach ( $autoBlocks as $block ) {
323  if ( !in_array( $block->mParentBlockId, $blockIds ) ) {
324  $blocks[] = $block;
325  }
326  }
327 
328  return $blocks;
329  }
330 
343  protected static function chooseMostSpecificBlock( array $blocks ) {
344  if ( count( $blocks ) === 1 ) {
345  return $blocks[0];
346  }
347 
348  # This result could contain a block on the user, a block on the IP, and a russian-doll
349  # set of rangeblocks. We want to choose the most specific one, so keep a leader board.
350  $bestBlock = null;
351 
352  # Lower will be better
353  $bestBlockScore = 100;
354  foreach ( $blocks as $block ) {
355  if ( $block->getType() == self::TYPE_RANGE ) {
356  # This is the number of bits that are allowed to vary in the block, give
357  # or take some floating point errors
358  $target = $block->getTarget();
359  $max = IPUtils::isIPv6( $target ) ? 128 : 32;
360  list( $network, $bits ) = IPUtils::parseCIDR( $target );
361  $size = $max - $bits;
362 
363  # Rank a range block covering a single IP equally with a single-IP block
364  $score = self::TYPE_RANGE - 1 + ( $size / $max );
365 
366  } else {
367  $score = $block->getType();
368  }
369 
370  if ( $score < $bestBlockScore ) {
371  $bestBlockScore = $score;
372  $bestBlock = $block;
373  }
374  }
375 
376  return $bestBlock;
377  }
378 
385  public static function getRangeCond( $start, $end = null ) {
386  if ( $end === null ) {
387  $end = $start;
388  }
389  # Per T16634, we want to include relevant active rangeblocks; for
390  # rangeblocks, we want to include larger ranges which enclose the given
391  # range. We know that all blocks must be smaller than $wgBlockCIDRLimit,
392  # so we can improve performance by filtering on a LIKE clause
393  $chunk = self::getIpFragment( $start );
394  $dbr = wfGetDB( DB_REPLICA );
395  $like = $dbr->buildLike( $chunk, $dbr->anyString() );
396 
397  # Fairly hard to make a malicious SQL statement out of hex characters,
398  # but stranger things have happened...
399  $safeStart = $dbr->addQuotes( $start );
400  $safeEnd = $dbr->addQuotes( $end );
401 
402  return $dbr->makeList(
403  [
404  "ipb_range_start $like",
405  "ipb_range_start <= $safeStart",
406  "ipb_range_end >= $safeEnd",
407  ],
408  LIST_AND
409  );
410  }
411 
418  protected static function getIpFragment( $hex ) {
419  global $wgBlockCIDRLimit;
420  if ( substr( $hex, 0, 3 ) == 'v6-' ) {
421  return 'v6-' . substr( substr( $hex, 3 ), 0, floor( $wgBlockCIDRLimit['IPv6'] / 4 ) );
422  } else {
423  return substr( $hex, 0, floor( $wgBlockCIDRLimit['IPv4'] / 4 ) );
424  }
425  }
426 
432  protected function initFromRow( $row ) {
433  $this->setTarget( $row->ipb_address );
434 
435  $this->setTimestamp( wfTimestamp( TS_MW, $row->ipb_timestamp ) );
436  $this->mAuto = (bool)$row->ipb_auto;
437  $this->setHideName( (bool)$row->ipb_deleted );
438  $this->mId = (int)$row->ipb_id;
439  $this->mParentBlockId = (int)$row->ipb_parent_block_id;
440 
442  $row->ipb_by, $row->ipb_by_text, $row->ipb_by_actor ?? null
443  ) );
444 
445  // I wish I didn't have to do this
446  $db = wfGetDB( DB_REPLICA );
447  $this->setExpiry( $db->decodeExpiry( $row->ipb_expiry ) );
448  $this->setReason(
450  // Legacy because $row may have come from self::selectFields()
451  ->getCommentLegacy( $db, 'ipb_reason', $row )
452  );
453 
454  $this->isHardblock( !$row->ipb_anon_only );
455  $this->isAutoblocking( (bool)$row->ipb_enable_autoblock );
456  $this->isSitewide( (bool)$row->ipb_sitewide );
457 
458  $this->isCreateAccountBlocked( (bool)$row->ipb_create_account );
459  $this->isEmailBlocked( (bool)$row->ipb_block_email );
460  $this->isUsertalkEditAllowed( (bool)$row->ipb_allow_usertalk );
461  }
462 
468  public static function newFromRow( $row ) {
469  $block = new DatabaseBlock;
470  $block->initFromRow( $row );
471  return $block;
472  }
473 
481  public function delete() {
483  ->getDatabaseBlockStore()
484  ->deleteBlock( $this );
485  }
486 
496  public function insert( IDatabase $dbw = null ) {
498  ->getDatabaseBlockStore()
499  ->insertBlock( $this, $dbw );
500  }
501 
510  public function update() {
512  ->getDatabaseBlockStore()
513  ->updateBlock( $this );
514  }
515 
523  public static function isWhitelistedFromAutoblocks( $ip ) {
524  // Try to get the autoblock_whitelist from the cache, as it's faster
525  // than getting the msg raw and explode()'ing it.
526  $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
527  $lines = $cache->getWithSetCallback(
528  $cache->makeKey( 'ip-autoblock', 'whitelist' ),
529  $cache::TTL_DAY,
530  function ( $curValue, &$ttl, array &$setOpts ) {
532 
533  return explode( "\n",
534  wfMessage( 'autoblock_whitelist' )->inContentLanguage()->plain() );
535  }
536  );
537 
538  wfDebug( "Checking the autoblock whitelist.." );
539 
540  foreach ( $lines as $line ) {
541  # List items only
542  if ( substr( $line, 0, 1 ) !== '*' ) {
543  continue;
544  }
545 
546  $wlEntry = substr( $line, 1 );
547  $wlEntry = trim( $wlEntry );
548 
549  wfDebug( "Checking $ip against $wlEntry..." );
550 
551  # Is the IP in this range?
552  if ( IPUtils::isInRange( $ip, $wlEntry ) ) {
553  wfDebug( " IP $ip matches $wlEntry, not autoblocking" );
554  return true;
555  } else {
556  wfDebug( " No match" );
557  }
558  }
559 
560  return false;
561  }
562 
569  public function doAutoblock( $autoblockIP ) {
570  # If autoblocks are disabled, go away.
571  if ( !$this->isAutoblocking() ) {
572  return false;
573  }
574 
575  # Check for presence on the autoblock whitelist.
576  if ( self::isWhitelistedFromAutoblocks( $autoblockIP ) ) {
577  return false;
578  }
579 
580  # Allow hooks to cancel the autoblock.
581  if ( !Hooks::runner()->onAbortAutoblock( $autoblockIP, $this ) ) {
582  wfDebug( "Autoblock aborted by hook." );
583  return false;
584  }
585 
586  # It's okay to autoblock. Go ahead and insert/update the block...
587 
588  # Do not add a *new* block if the IP is already blocked.
589  $ipblock = self::newFromTarget( $autoblockIP );
590  if ( $ipblock ) {
591  # Check if the block is an autoblock and would exceed the user block
592  # if renewed. If so, do nothing, otherwise prolong the block time...
593  if ( $ipblock->mAuto && // @todo Why not compare $ipblock->mExpiry?
594  $this->getExpiry() > self::getAutoblockExpiry( $ipblock->getTimestamp() )
595  ) {
596  # Reset block timestamp to now and its expiry to
597  # $wgAutoblockExpiry in the future
598  $ipblock->updateTimestamp();
599  }
600  return false;
601  }
602 
603  # Make a new block object with the desired properties.
604  $autoblock = new DatabaseBlock;
605  wfDebug( "Autoblocking {$this->getTarget()}@" . $autoblockIP );
606  $autoblock->setTarget( $autoblockIP );
607  $autoblock->setBlocker( $this->getBlocker() );
608  $autoblock->setReason(
609  wfMessage(
610  'autoblocker',
611  (string)$this->getTarget(),
612  $this->getReasonComment()->text
613  )->inContentLanguage()->plain()
614  );
615  $timestamp = wfTimestampNow();
616  $autoblock->setTimestamp( $timestamp );
617  $autoblock->mAuto = true;
618  $autoblock->isCreateAccountBlocked( $this->isCreateAccountBlocked() );
619  # Continue suppressing the name if needed
620  $autoblock->setHideName( $this->getHideName() );
621  $autoblock->isUsertalkEditAllowed( $this->isUsertalkEditAllowed() );
622  $autoblock->mParentBlockId = $this->mId;
623  $autoblock->isSitewide( $this->isSitewide() );
624  $autoblock->setRestrictions( $this->getRestrictions() );
625 
626  if ( $this->getExpiry() == 'infinity' ) {
627  # Original block was indefinite, start an autoblock now
628  $autoblock->setExpiry( self::getAutoblockExpiry( $timestamp ) );
629  } else {
630  # If the user is already blocked with an expiry date, we don't
631  # want to pile on top of that.
632  $autoblock->setExpiry( min( $this->getExpiry(), self::getAutoblockExpiry( $timestamp ) ) );
633  }
634 
635  # Insert the block...
636  $status = MediaWikiServices::getInstance()->getDatabaseBlockStore()->insertBlock(
637  $autoblock
638  );
639  return $status
640  ? $status['id']
641  : false;
642  }
643 
648  public function isExpired() {
649  $timestamp = wfTimestampNow();
650  wfDebug( __METHOD__ . " checking current " . $timestamp . " vs $this->mExpiry" );
651 
652  if ( !$this->getExpiry() ) {
653  return false;
654  } else {
655  return $timestamp > $this->getExpiry();
656  }
657  }
658 
662  public function updateTimestamp() {
663  if ( $this->mAuto ) {
664  $this->setTimestamp( wfTimestamp() );
665  $this->setExpiry( self::getAutoblockExpiry( $this->getTimestamp() ) );
666 
667  $dbw = wfGetDB( DB_MASTER );
668  $dbw->update( 'ipblocks',
669  [ /* SET */
670  'ipb_timestamp' => $dbw->timestamp( $this->getTimestamp() ),
671  'ipb_expiry' => $dbw->timestamp( $this->getExpiry() ),
672  ],
673  [ /* WHERE */
674  'ipb_id' => $this->getId(),
675  ],
676  __METHOD__
677  );
678  }
679  }
680 
686  public function getRangeStart() {
687  switch ( $this->type ) {
688  case self::TYPE_USER:
689  return '';
690  case self::TYPE_IP:
691  return IPUtils::toHex( $this->target );
692  case self::TYPE_RANGE:
693  list( $start, /*...*/ ) = IPUtils::parseRange( $this->target );
694  return $start;
695  default:
696  throw new MWException( "Block with invalid type" );
697  }
698  }
699 
705  public function getRangeEnd() {
706  switch ( $this->type ) {
707  case self::TYPE_USER:
708  return '';
709  case self::TYPE_IP:
710  return IPUtils::toHex( $this->target );
711  case self::TYPE_RANGE:
712  list( /*...*/, $end ) = IPUtils::parseRange( $this->target );
713  return $end;
714  default:
715  throw new MWException( "Block with invalid type" );
716  }
717  }
718 
723  public function getReason() {
724  if ( $this->getType() === self::TYPE_AUTO ) {
725  return $this->reason->message->inContentLanguage()->plain();
726  }
727  return $this->reason->text;
728  }
729 
733  public function getId() {
734  return $this->mId;
735  }
736 
744  public function setId( $blockId ) {
745  $this->mId = (int)$blockId;
746 
747  if ( is_array( $this->restrictions ) ) {
748  $this->restrictions = $this->getBlockRestrictionStore()->setBlockId(
749  $blockId, $this->restrictions
750  );
751  }
752 
753  return $this;
754  }
755 
760  public function getParentBlockId() {
761  return $this->mParentBlockId;
762  }
763 
769  public function isHardblock( $x = null ) {
770  wfSetVar( $this->isHardblock, $x );
771 
772  # You can't *not* hardblock a user
773  return $this->getType() == self::TYPE_USER
774  ? true
776  }
777 
782  public function isAutoblocking( $x = null ) {
783  wfSetVar( $this->isAutoblocking, $x );
784 
785  # You can't put an autoblock on an IP or range as we don't have any history to
786  # look over to get more IPs from
787  return $this->getType() == self::TYPE_USER
788  ? $this->isAutoblocking
789  : false;
790  }
791 
796  public function getRedactedName() {
797  if ( $this->mAuto ) {
798  return Html::element(
799  'span',
800  [ 'class' => 'mw-autoblockid' ],
801  wfMessage( 'autoblockid', $this->mId )->text()
802  );
803  } else {
804  return htmlspecialchars( $this->getTarget() );
805  }
806  }
807 
814  public static function getAutoblockExpiry( $timestamp ) {
815  global $wgAutoblockExpiry;
816 
817  return wfTimestamp( TS_MW, (int)wfTimestamp( TS_UNIX, $timestamp ) + $wgAutoblockExpiry );
818  }
819 
825  public static function purgeExpired() {
826  MediaWikiServices::getInstance()->getDatabaseBlockStore()->purgeExpiredBlocks();
827  }
828 
849  public static function newFromTarget( $specificTarget, $vagueTarget = null, $fromMaster = false ) {
850  $blocks = self::newListFromTarget( $specificTarget, $vagueTarget, $fromMaster );
851  return self::chooseMostSpecificBlock( $blocks );
852  }
853 
863  public static function newListFromTarget(
864  $specificTarget,
865  $vagueTarget = null,
866  $fromMaster = false
867  ) {
868  list( $target, $type ) = self::parseTarget( $specificTarget );
869  if ( $type == self::TYPE_ID || $type == self::TYPE_AUTO ) {
870  $block = self::newFromID( $target );
871  return $block ? [ $block ] : [];
872  } elseif ( $target === null && $vagueTarget == '' ) {
873  # We're not going to find anything useful here
874  # Be aware that the == '' check is explicit, since empty values will be
875  # passed by some callers (T31116)
876  return [];
877  } elseif ( in_array(
878  $type,
879  [ self::TYPE_USER, self::TYPE_IP, self::TYPE_RANGE, null ] )
880  ) {
881  return self::newLoad( $target, $type, $fromMaster, $vagueTarget );
882  }
883  return [];
884  }
885 
896  public static function getBlocksForIPList( array $ipChain, $isAnon, $fromMaster = false ) {
897  if ( $ipChain === [] ) {
898  return [];
899  }
900 
901  $conds = [];
902  $proxyLookup = MediaWikiServices::getInstance()->getProxyLookup();
903  foreach ( array_unique( $ipChain ) as $ipaddr ) {
904  # Discard invalid IP addresses. Since XFF can be spoofed and we do not
905  # necessarily trust the header given to us, make sure that we are only
906  # checking for blocks on well-formatted IP addresses (IPv4 and IPv6).
907  # Do not treat private IP spaces as special as it may be desirable for wikis
908  # to block those IP ranges in order to stop misbehaving proxies that spoof XFF.
909  if ( !IPUtils::isValid( $ipaddr ) ) {
910  continue;
911  }
912  # Don't check trusted IPs (includes local CDNs which will be in every request)
913  if ( $proxyLookup->isTrustedProxy( $ipaddr ) ) {
914  continue;
915  }
916  # Check both the original IP (to check against single blocks), as well as build
917  # the clause to check for rangeblocks for the given IP.
918  $conds['ipb_address'][] = $ipaddr;
919  $conds[] = self::getRangeCond( IPUtils::toHex( $ipaddr ) );
920  }
921 
922  if ( $conds === [] ) {
923  return [];
924  }
925 
926  if ( $fromMaster ) {
927  $db = wfGetDB( DB_MASTER );
928  } else {
929  $db = wfGetDB( DB_REPLICA );
930  }
931  $conds = $db->makeList( $conds, LIST_OR );
932  if ( !$isAnon ) {
933  $conds = [ $conds, 'ipb_anon_only' => 0 ];
934  }
935  $blockQuery = self::getQueryInfo();
936  $rows = $db->select(
937  $blockQuery['tables'],
938  array_merge( [ 'ipb_range_start', 'ipb_range_end' ], $blockQuery['fields'] ),
939  $conds,
940  __METHOD__,
941  [],
942  $blockQuery['joins']
943  );
944 
945  $blocks = [];
946  foreach ( $rows as $row ) {
947  $block = self::newFromRow( $row );
948  if ( !$block->isExpired() ) {
949  $blocks[] = $block;
950  }
951  }
952 
953  return $blocks;
954  }
955 
979  public static function chooseBlock( array $blocks, array $ipChain ) {
980  wfDeprecated( __METHOD__, '1.35' );
981  if ( $blocks === [] ) {
982  return null;
983  } elseif ( count( $blocks ) == 1 ) {
984  return $blocks[0];
985  }
986 
987  // Sort hard blocks before soft ones and secondarily sort blocks
988  // that disable account creation before those that don't.
989  usort( $blocks, function ( DatabaseBlock $a, DatabaseBlock $b ) {
990  $aWeight = (int)$a->isHardblock() . (int)$a->appliesToRight( 'createaccount' );
991  $bWeight = (int)$b->isHardblock() . (int)$b->appliesToRight( 'createaccount' );
992  return strcmp( $bWeight, $aWeight ); // highest weight first
993  } );
994 
995  $blocksListExact = [
996  'hard' => false,
997  'disable_create' => false,
998  'other' => false,
999  'auto' => false
1000  ];
1001  $blocksListRange = [
1002  'hard' => false,
1003  'disable_create' => false,
1004  'other' => false,
1005  'auto' => false
1006  ];
1007  $ipChain = array_reverse( $ipChain );
1008 
1009  foreach ( $blocks as $block ) {
1010  // Stop searching if we have already have a "better" block. This
1011  // is why the order of the blocks matters
1012  if ( !$block->isHardblock() && $blocksListExact['hard'] ) {
1013  break;
1014  } elseif ( !$block->appliesToRight( 'createaccount' ) && $blocksListExact['disable_create'] ) {
1015  break;
1016  }
1017 
1018  foreach ( $ipChain as $checkip ) {
1019  $checkipHex = IPUtils::toHex( $checkip );
1020  if ( (string)$block->getTarget() === $checkip ) {
1021  if ( $block->isHardblock() ) {
1022  $blocksListExact['hard'] = $blocksListExact['hard'] ?: $block;
1023  } elseif ( $block->appliesToRight( 'createaccount' ) ) {
1024  $blocksListExact['disable_create'] = $blocksListExact['disable_create'] ?: $block;
1025  } elseif ( $block->mAuto ) {
1026  $blocksListExact['auto'] = $blocksListExact['auto'] ?: $block;
1027  } else {
1028  $blocksListExact['other'] = $blocksListExact['other'] ?: $block;
1029  }
1030  // We found closest exact match in the ip list, so go to the next block
1031  break;
1032  } elseif ( array_filter( $blocksListExact ) == []
1033  && $block->getRangeStart() <= $checkipHex
1034  && $block->getRangeEnd() >= $checkipHex
1035  ) {
1036  if ( $block->isHardblock() ) {
1037  $blocksListRange['hard'] = $blocksListRange['hard'] ?: $block;
1038  } elseif ( $block->appliesToRight( 'createaccount' ) ) {
1039  $blocksListRange['disable_create'] = $blocksListRange['disable_create'] ?: $block;
1040  } elseif ( $block->mAuto ) {
1041  $blocksListRange['auto'] = $blocksListRange['auto'] ?: $block;
1042  } else {
1043  $blocksListRange['other'] = $blocksListRange['other'] ?: $block;
1044  }
1045  break;
1046  }
1047  }
1048  }
1049 
1050  if ( array_filter( $blocksListExact ) == [] ) {
1051  $blocksList = &$blocksListRange;
1052  } else {
1053  $blocksList = &$blocksListExact;
1054  }
1055 
1056  $chosenBlock = null;
1057  if ( $blocksList['hard'] ) {
1058  $chosenBlock = $blocksList['hard'];
1059  } elseif ( $blocksList['disable_create'] ) {
1060  $chosenBlock = $blocksList['disable_create'];
1061  } elseif ( $blocksList['other'] ) {
1062  $chosenBlock = $blocksList['other'];
1063  } elseif ( $blocksList['auto'] ) {
1064  $chosenBlock = $blocksList['auto'];
1065  } else {
1066  throw new MWException( "Proxy block found, but couldn't be classified." );
1067  }
1068 
1069  return $chosenBlock;
1070  }
1071 
1078  public function getType() {
1079  return $this->mAuto
1080  ? self::TYPE_AUTO
1081  : parent::getType();
1082  }
1083 
1087  public function getIdentifier() {
1088  return $this->getId();
1089  }
1090 
1098  public function getRestrictions() {
1099  if ( $this->restrictions === null ) {
1100  // If the block id has not been set, then do not attempt to load the
1101  // restrictions.
1102  if ( !$this->mId ) {
1103  return [];
1104  }
1105  $this->restrictions = $this->getBlockRestrictionStore()->loadByBlockId( $this->mId );
1106  }
1107 
1108  return $this->restrictions;
1109  }
1110 
1117  public function getRawRestrictions() : ?array {
1118  return $this->restrictions;
1119  }
1120 
1126  public function setRestrictions( array $restrictions ) {
1127  $this->restrictions = array_filter( $restrictions, function ( $restriction ) {
1128  return $restriction instanceof Restriction;
1129  } );
1130 
1131  return $this;
1132  }
1133 
1137  public function appliesToTitle( Title $title ) {
1138  if ( $this->isSitewide() ) {
1139  return true;
1140  }
1141 
1142  $restrictions = $this->getRestrictions();
1143  foreach ( $restrictions as $restriction ) {
1144  if ( $restriction->matches( $title ) ) {
1145  return true;
1146  }
1147  }
1148 
1149  return false;
1150  }
1151 
1155  public function appliesToNamespace( $ns ) {
1156  if ( $this->isSitewide() ) {
1157  return true;
1158  }
1159 
1160  // Blocks do not apply to virtual namespaces.
1161  if ( $ns < 0 ) {
1162  return false;
1163  }
1164 
1165  $restriction = $this->findRestriction( NamespaceRestriction::TYPE, $ns );
1166 
1167  return (bool)$restriction;
1168  }
1169 
1173  public function appliesToPage( $pageId ) {
1174  if ( $this->isSitewide() ) {
1175  return true;
1176  }
1177 
1178  // If the pageId is not over zero, the block cannot apply to it.
1179  if ( $pageId <= 0 ) {
1180  return false;
1181  }
1182 
1183  $restriction = $this->findRestriction( PageRestriction::TYPE, $pageId );
1184 
1185  return (bool)$restriction;
1186  }
1187 
1195  private function findRestriction( $type, $value ) {
1196  $restrictions = $this->getRestrictions();
1197  foreach ( $restrictions as $restriction ) {
1198  if ( $restriction->getType() !== $type ) {
1199  continue;
1200  }
1201 
1202  if ( $restriction->getValue() === $value ) {
1203  return $restriction;
1204  }
1205  }
1206 
1207  return null;
1208  }
1209 
1216  return MediaWikiServices::getInstance()->getBlockRestrictionStore();
1217  }
1218 
1222  public function getBy() {
1223  return ( $this->blocker ) ? $this->blocker->getId() : 0;
1224  }
1225 
1229  public function getByName() {
1230  return ( $this->blocker ) ? $this->blocker->getName() : '';
1231  }
1232 
1238  public function getBlocker() {
1239  return $this->blocker;
1240  }
1241 
1248  public function getForcedTargetID() : ?int {
1249  return $this->forcedTargetID;
1250  }
1251 
1257  public function setBlocker( $user ) {
1258  if ( is_string( $user ) ) {
1259  $user = User::newFromName( $user, false );
1260  }
1261 
1262  if ( $user->isAnon() &&
1263  MediaWikiServices::getInstance()->getUserNameUtils()->isUsable( $user->getName() )
1264  ) {
1265  // Temporarily log some block details to debug T192964
1266  $logger = LoggerFactory::getInstance( 'BlockManager' );
1267  $logger->warning(
1268  'Blocker is neither a local user nor an invalid username',
1269  [
1270  'blocker' => (string)$user,
1271  'blockId' => $this->getId(),
1272  ]
1273  );
1274  throw new \InvalidArgumentException(
1275  'Blocker must be a local user or a name that cannot be a local user'
1276  );
1277  }
1278 
1279  $this->blocker = $user;
1280  }
1281 }
1282 
1286 class_alias( DatabaseBlock::class, 'Block' );
LIST_OR
const LIST_OR
Definition: Defines.php:45
MediaWiki\Block\DatabaseBlock\setBlocker
setBlocker( $user)
Set the user who implemented (or will implement) this block.
Definition: DatabaseBlock.php:1257
MediaWiki\Block\DatabaseBlock\getIpFragment
static getIpFragment( $hex)
Get the component of an IP address which is certain to be the same between an IP address and a rangeb...
Definition: DatabaseBlock.php:418
Wikimedia\Rdbms\Database
Relational database abstraction object.
Definition: Database.php:50
User\newFromId
static newFromId( $id)
Static factory method for creation from a given user ID.
Definition: User.php:587
MediaWiki\Block\AbstractBlock\$target
User string null $target
Definition: AbstractBlock.php:78
MediaWiki\Block\DatabaseBlock\equals
equals(DatabaseBlock $block)
Check if two blocks are effectively equal.
Definition: DatabaseBlock.php:209
MediaWiki\Block
Definition: AbstractBlock.php:21
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:166
MediaWiki\Block\DatabaseBlock\chooseBlock
static chooseBlock(array $blocks, array $ipChain)
From a list of multiple blocks, find the most exact and strongest block.
Definition: DatabaseBlock.php:979
MediaWiki\Block\DatabaseBlock\initFromRow
initFromRow( $row)
Given a database row from the ipblocks table, initialize member variables.
Definition: DatabaseBlock.php:432
wfSetVar
wfSetVar(&$dest, $source, $force=false)
Sets dest to source and returns the original value of dest If source is NULL, it just returns the val...
Definition: GlobalFunctions.php:1560
MediaWiki\Logger\LoggerFactory\getInstance
static getInstance( $channel)
Get a named logger instance from the currently configured logger factory.
Definition: LoggerFactory.php:92
MediaWiki\Block\DatabaseBlock\getRangeStart
getRangeStart()
Get the IP address at the start of the range in Hex form.
Definition: DatabaseBlock.php:686
MediaWiki\Block\DatabaseBlock\$mParentBlockId
int $mParentBlockId
Definition: DatabaseBlock.php:61
true
return true
Definition: router.php:90
wfTimestamp
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
Definition: GlobalFunctions.php:1831
$wgAutoblockExpiry
$wgAutoblockExpiry
Number of seconds before autoblock entries expire.
Definition: DefaultSettings.php:5425
LIST_AND
const LIST_AND
Definition: Defines.php:42
MediaWiki\Block\DatabaseBlock\getType
getType()
Get the type of target for this particular block.int|null AbstractBlock::TYPE_ constant,...
Definition: DatabaseBlock.php:1078
MediaWiki\Block\Restriction\NamespaceRestriction\TYPE
const TYPE
Definition: NamespaceRestriction.php:30
MediaWiki\Block\AbstractBlock\isCreateAccountBlocked
isCreateAccountBlocked( $x=null)
Get or set the flag indicating whether this block blocks the target from creating an account.
Definition: AbstractBlock.php:233
MediaWiki\Block\DatabaseBlock\getBlocker
getBlocker()
Get the user who implemented this block.
Definition: DatabaseBlock.php:1238
MediaWiki\Block\DatabaseBlock\__construct
__construct(array $options=[])
Create a new block with specified option parameters on a user, IP or IP range.
Definition: DatabaseBlock.php:101
MediaWiki\Block\AbstractBlock\TYPE_AUTO
const TYPE_AUTO
Definition: AbstractBlock.php:94
CommentStore
Handle database storage of comments such as edit summaries and log reasons.
Definition: CommentStore.php:42
User\newFromName
static newFromName( $name, $validate='valid')
Definition: User.php:548
MediaWiki\Block\DatabaseBlock\appliesToNamespace
appliesToNamespace( $ns)
Checks if a block applies to a particular namespace.1.33bool
Definition: DatabaseBlock.php:1155
wfMessage
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
Definition: GlobalFunctions.php:1230
MediaWiki\Block\DatabaseBlock\getByName
getByName()
Get the username of the blocking sysop.string
Definition: DatabaseBlock.php:1229
ActorMigration
This class handles the logic for the actor table migration and should always be used in lieu of direc...
Definition: ActorMigration.php:41
$res
$res
Definition: testCompression.php:57
MediaWiki\Block\DatabaseBlock\getRawRestrictions
getRawRestrictions()
Get restrictions without loading from database if not yet loaded.
Definition: DatabaseBlock.php:1117
ActorMigration\newMigration
static newMigration()
Static constructor.
Definition: ActorMigration.php:156
Wikimedia\Rdbms\IDatabase
Basic database interface for live and lazy-loaded relation database handles.
Definition: IDatabase.php:38
$dbr
$dbr
Definition: testCompression.php:54
MediaWiki\MediaWikiServices\getInstance
static getInstance()
Returns the global default instance of the top level service locator.
Definition: MediaWikiServices.php:198
MediaWiki\Block\AbstractBlock\TYPE_RANGE
const TYPE_RANGE
Definition: AbstractBlock.php:93
MediaWiki\Block\DatabaseBlock\appliesToPage
appliesToPage( $pageId)
Checks if a block applies to a particular page.This check does not consider whether $this->isUsertalk...
Definition: DatabaseBlock.php:1173
MediaWiki\Block\DatabaseBlock
A DatabaseBlock (unlike a SystemBlock) is stored in the database, may give rise to autoblocks and may...
Definition: DatabaseBlock.php:50
MediaWiki\Block\DatabaseBlock\setRestrictions
setRestrictions(array $restrictions)
Definition: DatabaseBlock.php:1126
MediaWiki\Block\DatabaseBlock\getForcedTargetID
getForcedTargetID()
Get the forcedTargetID if set.
Definition: DatabaseBlock.php:1248
MWException
MediaWiki exception.
Definition: MWException.php:29
MediaWiki\Block\DatabaseBlock\getBlocksForIPList
static getBlocksForIPList(array $ipChain, $isAnon, $fromMaster=false)
Get all blocks that match any IP from an array of IP addresses.
Definition: DatabaseBlock.php:896
wfDeprecated
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that $function is deprecated.
Definition: GlobalFunctions.php:1033
MediaWiki\Logger\LoggerFactory
PSR-3 logger instance factory.
Definition: LoggerFactory.php:45
MediaWiki\Block\DatabaseBlock\$blocker
User $blocker
Definition: DatabaseBlock.php:79
Wikimedia\Rdbms\Database\getCacheSetOptions
static getCacheSetOptions(IDatabase $db1, IDatabase $db2=null)
Merge the result of getSessionLagStatus() for several DBs using the most pessimistic values to estima...
Definition: Database.php:4964
MediaWiki\Block\DatabaseBlock\$mFromMaster
bool $mFromMaster
Definition: DatabaseBlock.php:67
MediaWiki\Block\DatabaseBlock\purgeExpired
static purgeExpired()
Purge expired blocks from the ipblocks table.
Definition: DatabaseBlock.php:825
wfGetDB
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
Definition: GlobalFunctions.php:2466
MediaWiki\Block\AbstractBlock\isEmailBlocked
isEmailBlocked( $x=null)
Get or set the flag indicating whether this block blocks the target from sending emails.
Definition: AbstractBlock.php:246
MediaWiki\Block\DatabaseBlock\newFromRow
static newFromRow( $row)
Create a new DatabaseBlock object from a database row.
Definition: DatabaseBlock.php:468
MediaWiki\Block\Restriction\Restriction
Definition: Restriction.php:25
MediaWiki\Block\AbstractBlock\getReasonComment
getReasonComment()
Get the reason for creating the block.
Definition: AbstractBlock.php:177
MediaWiki\Block\DatabaseBlock\$forcedTargetID
int $forcedTargetID
Hack for foreign blocking (CentralAuth)
Definition: DatabaseBlock.php:70
MediaWiki\Block\Restriction\PageRestriction\TYPE
const TYPE
Definition: PageRestriction.php:30
MediaWiki\Block\DatabaseBlock\isWhitelistedFromAutoblocks
static isWhitelistedFromAutoblocks( $ip)
Checks whether a given IP is on the autoblock whitelist.
Definition: DatabaseBlock.php:523
MediaWiki\Block\AbstractBlock\TYPE_IP
const TYPE_IP
Definition: AbstractBlock.php:92
MediaWiki\Block\DatabaseBlock\getRangeEnd
getRangeEnd()
Get the IP address at the end of the range in Hex form.
Definition: DatabaseBlock.php:705
$title
$title
Definition: testCompression.php:38
DB_REPLICA
const DB_REPLICA
Definition: defines.php:25
wfTimestampNow
wfTimestampNow()
Convenience function; returns MediaWiki timestamp for the present time.
Definition: GlobalFunctions.php:1860
User\newFromAnyId
static newFromAnyId( $userId, $userName, $actorId, $dbDomain=false)
Static factory method for creation from an ID, name, and/or actor ID.
Definition: User.php:646
MediaWiki\Block\DatabaseBlock\isExpired
isExpired()
Has the block expired?
Definition: DatabaseBlock.php:648
MediaWiki\Block\AbstractBlock\isSitewide
isSitewide( $x=null)
Indicates that the block is a sitewide block.
Definition: AbstractBlock.php:220
DB_MASTER
const DB_MASTER
Definition: defines.php:26
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:914
MediaWiki\Block\AbstractBlock\$isHardblock
bool $isHardblock
Definition: AbstractBlock.php:75
MediaWiki\Block\DatabaseBlock\getRangeCond
static getRangeCond( $start, $end=null)
Get a set of SQL conditions which will select rangeblocks encompassing a given range.
Definition: DatabaseBlock.php:385
MediaWiki\Block\DatabaseBlock\getBlockRestrictionStore
getBlockRestrictionStore()
Get a BlockRestrictionStore instance.
Definition: DatabaseBlock.php:1215
MediaWiki\Block\DatabaseBlock\getRedactedName
getRedactedName()
Get the block name, but with autoblocked IPs hidden as per standard privacy policy.
Definition: DatabaseBlock.php:796
MediaWiki\Block\DatabaseBlock\isAutoblocking
isAutoblocking( $x=null)
Definition: DatabaseBlock.php:782
MediaWiki\Block\AbstractBlock\setTimestamp
setTimestamp( $timestamp)
Set the timestamp indicating when the block was created.
Definition: AbstractBlock.php:414
MediaWiki\Block\DatabaseBlock\getBy
getBy()
Get the user id of the blocking sysop.int (0 for foreign users)
Definition: DatabaseBlock.php:1222
MediaWiki\Block\AbstractBlock\parseTarget
static parseTarget( $target)
From an existing block, get the target and the type of target.
Definition: AbstractBlock.php:340
MediaWiki\Block\AbstractBlock\TYPE_USER
const TYPE_USER
Definition: AbstractBlock.php:91
MediaWiki\Block\DatabaseBlock\getIdentifier
getIdentifier()
Get the information that identifies this block, such that a user could look up everything that can be...
Definition: DatabaseBlock.php:1087
MediaWiki\Block\DatabaseBlock\getParentBlockId
getParentBlockId()
Definition: DatabaseBlock.php:760
MediaWiki\Block\DatabaseBlock\$isAutoblocking
bool $isAutoblocking
Definition: DatabaseBlock.php:73
MediaWiki\Block\DatabaseBlock\newLoad
static newLoad( $specificTarget, $specificType, $fromMaster, $vagueTarget=null)
Load blocks from the database which target the specific target exactly, or which cover the vague targ...
Definition: DatabaseBlock.php:243
MediaWiki\Block\DatabaseBlock\getReason
getReason()
Get the reason given for creating the block, as a string.Deprecated, since this gives the caller no c...
Definition: DatabaseBlock.php:723
Hooks\runner
static runner()
Get a HookRunner instance for calling hooks using the new interfaces.
Definition: Hooks.php:172
$line
$line
Definition: mcc.php:119
MediaWiki\Block\AbstractBlock\setExpiry
setExpiry( $expiry)
Set the block expiry time.
Definition: AbstractBlock.php:394
MediaWiki\Block\AbstractBlock\getExpiry
getExpiry()
Get the block expiry time.
Definition: AbstractBlock.php:384
MediaWiki\Block\DatabaseBlock\update
update()
Update a block in the DB with new parameters.
Definition: DatabaseBlock.php:510
$lines
if(!file_exists( $CREDITS)) $lines
Definition: updateCredits.php:45
MediaWiki\Block\Restriction\NamespaceRestriction
Definition: NamespaceRestriction.php:25
MediaWiki\Block\AbstractBlock\getTimestamp
getTimestamp()
Get the timestamp indicating when the block was created.
Definition: AbstractBlock.php:404
MediaWiki\Block\DatabaseBlock\getId
getId()
Get the block ID.int|null
Definition: DatabaseBlock.php:733
Title
Represents a title within MediaWiki.
Definition: Title.php:46
$wgBlockCIDRLimit
$wgBlockCIDRLimit
Limits on the possible sizes of range blocks.
Definition: DefaultSettings.php:5450
MediaWiki\Block\DatabaseBlock\setId
setId( $blockId)
Set the block ID.
Definition: DatabaseBlock.php:744
MediaWiki\Block\AbstractBlock\appliesToRight
appliesToRight( $right)
Determine whether the block prevents a given right.
Definition: AbstractBlock.php:291
$cache
$cache
Definition: mcc.php:33
MediaWiki\Block\DatabaseBlock\chooseMostSpecificBlock
static chooseMostSpecificBlock(array $blocks)
Choose the most specific block from some combination of user, IP and IP range blocks.
Definition: DatabaseBlock.php:343
MediaWiki\Block\Restriction\PageRestriction
Definition: PageRestriction.php:25
MediaWiki\Block\AbstractBlock\setReason
setReason( $reason)
Set the reason for creating the block.
Definition: AbstractBlock.php:187
MediaWiki\Block\DatabaseBlock\getRestrictions
getRestrictions()
Getting the restrictions will perform a database query if the restrictions are not already loaded.
Definition: DatabaseBlock.php:1098
MediaWiki\Block\DatabaseBlock\updateTimestamp
updateTimestamp()
Update the timestamp on autoblocks.
Definition: DatabaseBlock.php:662
MediaWiki\Block\DatabaseBlock\getQueryInfo
static getQueryInfo()
Return the tables, fields, and join conditions to be selected to create a new block object.
Definition: DatabaseBlock.php:178
MediaWiki\Block\DatabaseBlock\doAutoblock
doAutoblock( $autoblockIP)
Autoblocks the given IP, referring to this block.
Definition: DatabaseBlock.php:569
MediaWiki\Block\DatabaseBlock\findRestriction
findRestriction( $type, $value)
Find Restriction by type and value.
Definition: DatabaseBlock.php:1195
MediaWiki\Block\DatabaseBlock\newFromTarget
static newFromTarget( $specificTarget, $vagueTarget=null, $fromMaster=false)
Given a target and the target's type, get an existing block object if possible.
Definition: DatabaseBlock.php:849
MediaWiki\Block\DatabaseBlock\getAutoblockExpiry
static getAutoblockExpiry( $timestamp)
Get a timestamp of the expiry for autoblocks.
Definition: DatabaseBlock.php:814
MediaWiki\Block\AbstractBlock\getHideName
getHideName()
Get whether the block hides the target's username.
Definition: AbstractBlock.php:197
MediaWiki\Block\AbstractBlock\$type
int null $type
AbstractBlock::TYPE_ constant.
Definition: AbstractBlock.php:84
MediaWiki\Block\AbstractBlock
Definition: AbstractBlock.php:37
Html\element
static element( $element, $attribs=[], $contents='')
Identical to rawElement(), but HTML-escapes $contents (like Xml::element()).
Definition: Html.php:234
MediaWiki\Block\DatabaseBlock\$mAuto
bool $mAuto
Definition: DatabaseBlock.php:55
MediaWiki\Block\AbstractBlock\setTarget
setTarget( $target)
Set the target for this block, and update $this->type accordingly.
Definition: AbstractBlock.php:422
CommentStore\getStore
static getStore()
Definition: CommentStore.php:120
User
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:56
MediaWiki\Block\DatabaseBlock\insert
insert(IDatabase $dbw=null)
Insert a block into the block table.
Definition: DatabaseBlock.php:496
MediaWiki\Block\DatabaseBlock\appliesToTitle
appliesToTitle(Title $title)
Checks if a block applies to a particular title.This check does not consider whether $this->isUsertal...
Definition: DatabaseBlock.php:1137
MediaWiki\Block\AbstractBlock\getTarget
getTarget()
Get the target for this particular block.
Definition: AbstractBlock.php:374
MediaWiki\Block\DatabaseBlock\isHardblock
isHardblock( $x=null)
Get/set whether the block is a hardblock (affects logged-in users on a given IP/range)
Definition: DatabaseBlock.php:769
MediaWiki\Block\DatabaseBlock\newListFromTarget
static newListFromTarget( $specificTarget, $vagueTarget=null, $fromMaster=false)
This is similar to DatabaseBlock::newFromTarget, but it returns all the relevant blocks.
Definition: DatabaseBlock.php:863
MediaWiki\Block\DatabaseBlock\$restrictions
Restriction[] $restrictions
Definition: DatabaseBlock.php:76
MediaWiki\Block\AbstractBlock\isUsertalkEditAllowed
isUsertalkEditAllowed( $x=null)
Get or set the flag indicating whether this block blocks the target from editing their own user talk ...
Definition: AbstractBlock.php:259
MediaWiki\Block\DatabaseBlock\$mId
int $mId
Definition: DatabaseBlock.php:64
Hooks
Hooks class.
Definition: Hooks.php:38
MediaWiki\Block\BlockRestrictionStore
Definition: BlockRestrictionStore.php:34
MediaWiki\Block\DatabaseBlock\newFromID
static newFromID( $id)
Load a block from the block id.
Definition: DatabaseBlock.php:151
Html
This class is a collection of static functions that serve two purposes:
Definition: Html.php:49