MediaWiki  master
DatabaseBlock.php
Go to the documentation of this file.
1 <?php
23 namespace MediaWiki\Block;
24 
25 use ActorMigration;
27 use CommentStore;
28 use DeferredUpdates;
29 use Hooks;
30 use Html;
31 use IP;
36 use MWException;
37 use RequestContext;
38 use stdClass;
39 use Title;
40 use User;
41 use WebResponse;
44 
58  public $mAuto;
59 
65 
67  private $mId;
68 
70  private $mFromMaster;
71 
73  private $forcedTargetID;
74 
76  private $isHardblock;
77 
79  private $isAutoblocking;
80 
82  private $restrictions;
83 
85  private $blocker;
86 
107  public function __construct( array $options = [] ) {
108  parent::__construct( $options );
109 
110  $defaults = [
111  'user' => null,
112  'auto' => false,
113  'expiry' => '',
114  'anonOnly' => false,
115  'createAccount' => false,
116  'enableAutoblock' => false,
117  'blockEmail' => false,
118  'allowUsertalk' => false,
119  'sitewide' => true,
120  'by' => null,
121  'byText' => '',
122  ];
123 
124  $options += $defaults;
125 
126  if ( $this->target instanceof User && $options['user'] ) {
127  # Needed for foreign users
128  $this->forcedTargetID = $options['user'];
129  }
130 
131  if ( $options['by'] ) {
132  # Local user
133  $this->setBlocker( User::newFromId( $options['by'] ) );
134  } else {
135  # Foreign user
136  $this->setBlocker( $options['byText'] );
137  }
138 
139  $this->setExpiry( wfGetDB( DB_REPLICA )->decodeExpiry( $options['expiry'] ) );
140 
141  # Boolean settings
142  $this->mAuto = (bool)$options['auto'];
143  $this->isHardblock( !$options['anonOnly'] );
144  $this->isAutoblocking( (bool)$options['enableAutoblock'] );
145  $this->isSitewide( (bool)$options['sitewide'] );
146  $this->isEmailBlocked( (bool)$options['blockEmail'] );
147  $this->isCreateAccountBlocked( (bool)$options['createAccount'] );
148  $this->isUsertalkEditAllowed( (bool)$options['allowUsertalk'] );
149 
150  $this->mFromMaster = false;
151  }
152 
159  public static function newFromID( $id ) {
160  $dbr = wfGetDB( DB_REPLICA );
161  $blockQuery = self::getQueryInfo();
162  $res = $dbr->selectRow(
163  $blockQuery['tables'],
164  $blockQuery['fields'],
165  [ 'ipb_id' => $id ],
166  __METHOD__,
167  [],
168  $blockQuery['joins']
169  );
170  if ( $res ) {
171  return self::newFromRow( $res );
172  } else {
173  return null;
174  }
175  }
176 
186  public static function getQueryInfo() {
187  $commentQuery = CommentStore::getStore()->getJoin( 'ipb_reason' );
188  $actorQuery = ActorMigration::newMigration()->getJoin( 'ipb_by' );
189  return [
190  'tables' => [ 'ipblocks' ] + $commentQuery['tables'] + $actorQuery['tables'],
191  'fields' => [
192  'ipb_id',
193  'ipb_address',
194  'ipb_timestamp',
195  'ipb_auto',
196  'ipb_anon_only',
197  'ipb_create_account',
198  'ipb_enable_autoblock',
199  'ipb_expiry',
200  'ipb_deleted',
201  'ipb_block_email',
202  'ipb_allow_usertalk',
203  'ipb_parent_block_id',
204  'ipb_sitewide',
205  ] + $commentQuery['fields'] + $actorQuery['fields'],
206  'joins' => $commentQuery['joins'] + $actorQuery['joins'],
207  ];
208  }
209 
217  public function equals( DatabaseBlock $block ) {
218  return (
219  (string)$this->target == (string)$block->target
220  && $this->type == $block->type
221  && $this->mAuto == $block->mAuto
222  && $this->isHardblock() == $block->isHardblock()
223  && $this->isCreateAccountBlocked() == $block->isCreateAccountBlocked()
224  && $this->getExpiry() == $block->getExpiry()
225  && $this->isAutoblocking() == $block->isAutoblocking()
226  && $this->getHideName() == $block->getHideName()
227  && $this->isEmailBlocked() == $block->isEmailBlocked()
228  && $this->isUsertalkEditAllowed() == $block->isUsertalkEditAllowed()
229  && $this->getReasonComment()->text == $block->getReasonComment()->text
230  && $this->isSitewide() == $block->isSitewide()
231  // DatabaseBlock::getRestrictions() may perform a database query, so
232  // keep it at the end.
233  && $this->getBlockRestrictionStore()->equals(
234  $this->getRestrictions(), $block->getRestrictions()
235  )
236  );
237  }
238 
251  protected static function newLoad(
252  $specificTarget,
253  $specificType,
254  $fromMaster,
255  $vagueTarget = null
256  ) {
257  $db = wfGetDB( $fromMaster ? DB_MASTER : DB_REPLICA );
258 
259  if ( $specificType !== null ) {
260  $conds = [
261  'ipb_address' => [ (string)$specificTarget ],
262  ];
263  } else {
264  $conds = [ 'ipb_address' => [] ];
265  }
266 
267  # Be aware that the != '' check is explicit, since empty values will be
268  # passed by some callers (T31116)
269  if ( $vagueTarget != '' ) {
270  list( $target, $type ) = self::parseTarget( $vagueTarget );
271  switch ( $type ) {
272  case self::TYPE_USER:
273  # Slightly weird, but who are we to argue?
274  $conds['ipb_address'][] = (string)$target;
275  break;
276 
277  case self::TYPE_IP:
278  $conds['ipb_address'][] = (string)$target;
279  $conds[] = self::getRangeCond( IP::toHex( $target ) );
280  $conds = $db->makeList( $conds, LIST_OR );
281  break;
282 
283  case self::TYPE_RANGE:
284  list( $start, $end ) = IP::parseRange( $target );
285  $conds['ipb_address'][] = (string)$target;
286  $conds[] = self::getRangeCond( $start, $end );
287  $conds = $db->makeList( $conds, LIST_OR );
288  break;
289 
290  default:
291  throw new MWException( "Tried to load block with invalid type" );
292  }
293  }
294 
295  $blockQuery = self::getQueryInfo();
296  $res = $db->select(
297  $blockQuery['tables'], $blockQuery['fields'], $conds, __METHOD__, [], $blockQuery['joins']
298  );
299 
300  $blocks = [];
301  $blockIds = [];
302  $autoBlocks = [];
303  foreach ( $res as $row ) {
304  $block = self::newFromRow( $row );
305 
306  # Don't use expired blocks
307  if ( $block->isExpired() ) {
308  continue;
309  }
310 
311  # Don't use anon only blocks on users
312  if ( $specificType == self::TYPE_USER && !$block->isHardblock() ) {
313  continue;
314  }
315 
316  // Check for duplicate autoblocks
317  if ( $block->getType() === self::TYPE_AUTO ) {
318  $autoBlocks[] = $block;
319  } else {
320  $blocks[] = $block;
321  $blockIds[] = $block->getId();
322  }
323  }
324 
325  // Only add autoblocks that aren't duplicates
326  foreach ( $autoBlocks as $block ) {
327  if ( !in_array( $block->mParentBlockId, $blockIds ) ) {
328  $blocks[] = $block;
329  }
330  }
331 
332  return $blocks;
333  }
334 
347  protected static function chooseMostSpecificBlock( array $blocks ) {
348  if ( count( $blocks ) === 1 ) {
349  return $blocks[0];
350  }
351 
352  # This result could contain a block on the user, a block on the IP, and a russian-doll
353  # set of rangeblocks. We want to choose the most specific one, so keep a leader board.
354  $bestBlock = null;
355 
356  # Lower will be better
357  $bestBlockScore = 100;
358  foreach ( $blocks as $block ) {
359  if ( $block->getType() == self::TYPE_RANGE ) {
360  # This is the number of bits that are allowed to vary in the block, give
361  # or take some floating point errors
362  $target = $block->getTarget();
363  $max = IP::isIPv6( $target ) ? 128 : 32;
364  list( $network, $bits ) = IP::parseCIDR( $target );
365  $size = $max - $bits;
366 
367  # Rank a range block covering a single IP equally with a single-IP block
368  $score = self::TYPE_RANGE - 1 + ( $size / $max );
369 
370  } else {
371  $score = $block->getType();
372  }
373 
374  if ( $score < $bestBlockScore ) {
375  $bestBlockScore = $score;
376  $bestBlock = $block;
377  }
378  }
379 
380  return $bestBlock;
381  }
382 
389  public static function getRangeCond( $start, $end = null ) {
390  if ( $end === null ) {
391  $end = $start;
392  }
393  # Per T16634, we want to include relevant active rangeblocks; for
394  # rangeblocks, we want to include larger ranges which enclose the given
395  # range. We know that all blocks must be smaller than $wgBlockCIDRLimit,
396  # so we can improve performance by filtering on a LIKE clause
397  $chunk = self::getIpFragment( $start );
398  $dbr = wfGetDB( DB_REPLICA );
399  $like = $dbr->buildLike( $chunk, $dbr->anyString() );
400 
401  # Fairly hard to make a malicious SQL statement out of hex characters,
402  # but stranger things have happened...
403  $safeStart = $dbr->addQuotes( $start );
404  $safeEnd = $dbr->addQuotes( $end );
405 
406  return $dbr->makeList(
407  [
408  "ipb_range_start $like",
409  "ipb_range_start <= $safeStart",
410  "ipb_range_end >= $safeEnd",
411  ],
412  LIST_AND
413  );
414  }
415 
422  protected static function getIpFragment( $hex ) {
423  global $wgBlockCIDRLimit;
424  if ( substr( $hex, 0, 3 ) == 'v6-' ) {
425  return 'v6-' . substr( substr( $hex, 3 ), 0, floor( $wgBlockCIDRLimit['IPv6'] / 4 ) );
426  } else {
427  return substr( $hex, 0, floor( $wgBlockCIDRLimit['IPv4'] / 4 ) );
428  }
429  }
430 
436  protected function initFromRow( $row ) {
437  $this->setTarget( $row->ipb_address );
439  $row->ipb_by, $row->ipb_by_text, $row->ipb_by_actor ?? null
440  ) );
441 
442  $this->setTimestamp( wfTimestamp( TS_MW, $row->ipb_timestamp ) );
443  $this->mAuto = $row->ipb_auto;
444  $this->setHideName( $row->ipb_deleted );
445  $this->mId = (int)$row->ipb_id;
446  $this->mParentBlockId = $row->ipb_parent_block_id;
447 
448  // I wish I didn't have to do this
449  $db = wfGetDB( DB_REPLICA );
450  $this->setExpiry( $db->decodeExpiry( $row->ipb_expiry ) );
451  $this->setReason(
453  // Legacy because $row may have come from self::selectFields()
454  ->getCommentLegacy( $db, 'ipb_reason', $row )
455  );
456 
457  $this->isHardblock( !$row->ipb_anon_only );
458  $this->isAutoblocking( $row->ipb_enable_autoblock );
459  $this->isSitewide( (bool)$row->ipb_sitewide );
460 
461  $this->isCreateAccountBlocked( $row->ipb_create_account );
462  $this->isEmailBlocked( $row->ipb_block_email );
463  $this->isUsertalkEditAllowed( $row->ipb_allow_usertalk );
464  }
465 
471  public static function newFromRow( $row ) {
472  $block = new DatabaseBlock;
473  $block->initFromRow( $row );
474  return $block;
475  }
476 
483  public function delete() {
484  if ( wfReadOnly() ) {
485  return false;
486  }
487 
488  if ( !$this->getId() ) {
489  throw new MWException(
490  __METHOD__ . " requires that the mId member be filled\n"
491  );
492  }
493 
494  $dbw = wfGetDB( DB_MASTER );
495 
496  $this->getBlockRestrictionStore()->deleteByParentBlockId( $this->getId() );
497  $dbw->delete( 'ipblocks', [ 'ipb_parent_block_id' => $this->getId() ], __METHOD__ );
498 
499  $this->getBlockRestrictionStore()->deleteByBlockId( $this->getId() );
500  $dbw->delete( 'ipblocks', [ 'ipb_id' => $this->getId() ], __METHOD__ );
501 
502  return $dbw->affectedRows() > 0;
503  }
504 
513  public function insert( IDatabase $dbw = null ) {
514  global $wgBlockDisablesLogin;
515 
516  if ( !$this->getBlocker() || $this->getBlocker()->getName() === '' ) {
517  throw new MWException( 'Cannot insert a block without a blocker set' );
518  }
519 
520  wfDebug( __METHOD__ . "; timestamp {$this->mTimestamp}\n" );
521 
522  if ( $dbw === null ) {
523  $dbw = wfGetDB( DB_MASTER );
524  }
525 
526  self::purgeExpired();
527 
528  $row = $this->getDatabaseArray( $dbw );
529 
530  $dbw->insert( 'ipblocks', $row, __METHOD__, [ 'IGNORE' ] );
531  $affected = $dbw->affectedRows();
532  if ( $affected ) {
533  $this->setId( $dbw->insertId() );
534  if ( $this->restrictions ) {
535  $this->getBlockRestrictionStore()->insert( $this->restrictions );
536  }
537  }
538 
539  # Don't collide with expired blocks.
540  # Do this after trying to insert to avoid locking.
541  if ( !$affected ) {
542  # T96428: The ipb_address index uses a prefix on a field, so
543  # use a standard SELECT + DELETE to avoid annoying gap locks.
544  $ids = $dbw->selectFieldValues( 'ipblocks',
545  'ipb_id',
546  [
547  'ipb_address' => $row['ipb_address'],
548  'ipb_user' => $row['ipb_user'],
549  'ipb_expiry < ' . $dbw->addQuotes( $dbw->timestamp() )
550  ],
551  __METHOD__
552  );
553  if ( $ids ) {
554  $dbw->delete( 'ipblocks', [ 'ipb_id' => $ids ], __METHOD__ );
555  $this->getBlockRestrictionStore()->deleteByBlockId( $ids );
556  $dbw->insert( 'ipblocks', $row, __METHOD__, [ 'IGNORE' ] );
557  $affected = $dbw->affectedRows();
558  $this->setId( $dbw->insertId() );
559  if ( $this->restrictions ) {
560  $this->getBlockRestrictionStore()->insert( $this->restrictions );
561  }
562  }
563  }
564 
565  if ( $affected ) {
566  $auto_ipd_ids = $this->doRetroactiveAutoblock();
567 
568  if ( $wgBlockDisablesLogin && $this->target instanceof User ) {
569  // Change user login token to force them to be logged out.
570  $this->target->setToken();
571  $this->target->saveSettings();
572  }
573 
574  return [ 'id' => $this->mId, 'autoIds' => $auto_ipd_ids ];
575  }
576 
577  return false;
578  }
579 
587  public function update() {
588  wfDebug( __METHOD__ . "; timestamp {$this->mTimestamp}\n" );
589  $dbw = wfGetDB( DB_MASTER );
590 
591  $dbw->startAtomic( __METHOD__ );
592 
593  $result = $dbw->update(
594  'ipblocks',
595  $this->getDatabaseArray( $dbw ),
596  [ 'ipb_id' => $this->getId() ],
597  __METHOD__
598  );
599 
600  // Only update the restrictions if they have been modified.
601  if ( $this->restrictions !== null ) {
602  // An empty array should remove all of the restrictions.
603  if ( empty( $this->restrictions ) ) {
604  $success = $this->getBlockRestrictionStore()->deleteByBlockId( $this->getId() );
605  } else {
606  $success = $this->getBlockRestrictionStore()->update( $this->restrictions );
607  }
608  // Update the result. The first false is the result, otherwise, true.
609  $result = $result && $success;
610  }
611 
612  if ( $this->isAutoblocking() ) {
613  // update corresponding autoblock(s) (T50813)
614  $dbw->update(
615  'ipblocks',
616  $this->getAutoblockUpdateArray( $dbw ),
617  [ 'ipb_parent_block_id' => $this->getId() ],
618  __METHOD__
619  );
620 
621  // Only update the restrictions if they have been modified.
622  if ( $this->restrictions !== null ) {
623  $this->getBlockRestrictionStore()->updateByParentBlockId( $this->getId(), $this->restrictions );
624  }
625  } else {
626  // autoblock no longer required, delete corresponding autoblock(s)
627  $this->getBlockRestrictionStore()->deleteByParentBlockId( $this->getId() );
628  $dbw->delete(
629  'ipblocks',
630  [ 'ipb_parent_block_id' => $this->getId() ],
631  __METHOD__
632  );
633  }
634 
635  $dbw->endAtomic( __METHOD__ );
636 
637  if ( $result ) {
638  $auto_ipd_ids = $this->doRetroactiveAutoblock();
639  return [ 'id' => $this->mId, 'autoIds' => $auto_ipd_ids ];
640  }
641 
642  return $result;
643  }
644 
650  protected function getDatabaseArray( IDatabase $dbw ) {
651  $expiry = $dbw->encodeExpiry( $this->getExpiry() );
652 
653  if ( $this->forcedTargetID ) {
654  $uid = $this->forcedTargetID;
655  } else {
656  $uid = $this->target instanceof User ? $this->target->getId() : 0;
657  }
658 
659  $a = [
660  'ipb_address' => (string)$this->target,
661  'ipb_user' => $uid,
662  'ipb_timestamp' => $dbw->timestamp( $this->getTimestamp() ),
663  'ipb_auto' => $this->mAuto,
664  'ipb_anon_only' => !$this->isHardblock(),
665  'ipb_create_account' => $this->isCreateAccountBlocked(),
666  'ipb_enable_autoblock' => $this->isAutoblocking(),
667  'ipb_expiry' => $expiry,
668  'ipb_range_start' => $this->getRangeStart(),
669  'ipb_range_end' => $this->getRangeEnd(),
670  'ipb_deleted' => intval( $this->getHideName() ), // typecast required for SQLite
671  'ipb_block_email' => $this->isEmailBlocked(),
672  'ipb_allow_usertalk' => $this->isUsertalkEditAllowed(),
673  'ipb_parent_block_id' => $this->mParentBlockId,
674  'ipb_sitewide' => $this->isSitewide(),
675  ] + CommentStore::getStore()->insert( $dbw, 'ipb_reason', $this->getReasonComment() )
676  + ActorMigration::newMigration()->getInsertValues( $dbw, 'ipb_by', $this->getBlocker() );
677 
678  return $a;
679  }
680 
685  protected function getAutoblockUpdateArray( IDatabase $dbw ) {
686  return [
687  'ipb_create_account' => $this->isCreateAccountBlocked(),
688  'ipb_deleted' => (int)$this->getHideName(), // typecast required for SQLite
689  'ipb_allow_usertalk' => $this->isUsertalkEditAllowed(),
690  'ipb_sitewide' => $this->isSitewide(),
691  ] + CommentStore::getStore()->insert( $dbw, 'ipb_reason', $this->getReasonComment() )
692  + ActorMigration::newMigration()->getInsertValues( $dbw, 'ipb_by', $this->getBlocker() );
693  }
694 
701  protected function doRetroactiveAutoblock() {
702  $blockIds = [];
703  # If autoblock is enabled, autoblock the LAST IP(s) used
704  if ( $this->isAutoblocking() && $this->getType() == self::TYPE_USER ) {
705  wfDebug( "Doing retroactive autoblocks for " . $this->getTarget() . "\n" );
706 
707  $continue = Hooks::run(
708  'PerformRetroactiveAutoblock', [ $this, &$blockIds ] );
709 
710  if ( $continue ) {
711  self::defaultRetroactiveAutoblock( $this, $blockIds );
712  }
713  }
714  return $blockIds;
715  }
716 
724  protected static function defaultRetroactiveAutoblock( DatabaseBlock $block, array &$blockIds ) {
725  global $wgPutIPinRC;
726 
727  // No IPs are in recentchanges table, so nothing to select
728  if ( !$wgPutIPinRC ) {
729  return;
730  }
731 
732  // Autoblocks only apply to TYPE_USER
733  if ( $block->getType() !== self::TYPE_USER ) {
734  return;
735  }
736  $target = $block->getTarget(); // TYPE_USER => always a User object
737 
738  $dbr = wfGetDB( DB_REPLICA );
739  $rcQuery = ActorMigration::newMigration()->getWhere( $dbr, 'rc_user', $target, false );
740 
741  $options = [ 'ORDER BY' => 'rc_timestamp DESC' ];
742 
743  // Just the last IP used.
744  $options['LIMIT'] = 1;
745 
746  $res = $dbr->select(
747  [ 'recentchanges' ] + $rcQuery['tables'],
748  [ 'rc_ip' ],
749  $rcQuery['conds'],
750  __METHOD__,
751  $options,
752  $rcQuery['joins']
753  );
754 
755  if ( !$res->numRows() ) {
756  # No results, don't autoblock anything
757  wfDebug( "No IP found to retroactively autoblock\n" );
758  } else {
759  foreach ( $res as $row ) {
760  if ( $row->rc_ip ) {
761  $id = $block->doAutoblock( $row->rc_ip );
762  if ( $id ) {
763  $blockIds[] = $id;
764  }
765  }
766  }
767  }
768  }
769 
777  public static function isWhitelistedFromAutoblocks( $ip ) {
778  // Try to get the autoblock_whitelist from the cache, as it's faster
779  // than getting the msg raw and explode()'ing it.
780  $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
781  $lines = $cache->getWithSetCallback(
782  $cache->makeKey( 'ip-autoblock', 'whitelist' ),
783  $cache::TTL_DAY,
784  function ( $curValue, &$ttl, array &$setOpts ) {
786 
787  return explode( "\n",
788  wfMessage( 'autoblock_whitelist' )->inContentLanguage()->plain() );
789  }
790  );
791 
792  wfDebug( "Checking the autoblock whitelist..\n" );
793 
794  foreach ( $lines as $line ) {
795  # List items only
796  if ( substr( $line, 0, 1 ) !== '*' ) {
797  continue;
798  }
799 
800  $wlEntry = substr( $line, 1 );
801  $wlEntry = trim( $wlEntry );
802 
803  wfDebug( "Checking $ip against $wlEntry..." );
804 
805  # Is the IP in this range?
806  if ( IP::isInRange( $ip, $wlEntry ) ) {
807  wfDebug( " IP $ip matches $wlEntry, not autoblocking\n" );
808  return true;
809  } else {
810  wfDebug( " No match\n" );
811  }
812  }
813 
814  return false;
815  }
816 
823  public function doAutoblock( $autoblockIP ) {
824  # If autoblocks are disabled, go away.
825  if ( !$this->isAutoblocking() ) {
826  return false;
827  }
828 
829  # Check for presence on the autoblock whitelist.
830  if ( self::isWhitelistedFromAutoblocks( $autoblockIP ) ) {
831  return false;
832  }
833 
834  // Avoid PHP 7.1 warning of passing $this by reference
835  $block = $this;
836  # Allow hooks to cancel the autoblock.
837  if ( !Hooks::run( 'AbortAutoblock', [ $autoblockIP, &$block ] ) ) {
838  wfDebug( "Autoblock aborted by hook.\n" );
839  return false;
840  }
841 
842  # It's okay to autoblock. Go ahead and insert/update the block...
843 
844  # Do not add a *new* block if the IP is already blocked.
845  $ipblock = self::newFromTarget( $autoblockIP );
846  if ( $ipblock ) {
847  # Check if the block is an autoblock and would exceed the user block
848  # if renewed. If so, do nothing, otherwise prolong the block time...
849  if ( $ipblock->mAuto && // @todo Why not compare $ipblock->mExpiry?
850  $this->getExpiry() > self::getAutoblockExpiry( $ipblock->getTimestamp() )
851  ) {
852  # Reset block timestamp to now and its expiry to
853  # $wgAutoblockExpiry in the future
854  $ipblock->updateTimestamp();
855  }
856  return false;
857  }
858 
859  # Make a new block object with the desired properties.
860  $autoblock = new DatabaseBlock;
861  wfDebug( "Autoblocking {$this->getTarget()}@" . $autoblockIP . "\n" );
862  $autoblock->setTarget( $autoblockIP );
863  $autoblock->setBlocker( $this->getBlocker() );
864  $autoblock->setReason(
865  wfMessage(
866  'autoblocker',
867  (string)$this->getTarget(),
868  $this->getReasonComment()->text
869  )->plain()
870  );
871  $timestamp = wfTimestampNow();
872  $autoblock->setTimestamp( $timestamp );
873  $autoblock->mAuto = 1;
874  $autoblock->isCreateAccountBlocked( $this->isCreateAccountBlocked() );
875  # Continue suppressing the name if needed
876  $autoblock->setHideName( $this->getHideName() );
877  $autoblock->isUsertalkEditAllowed( $this->isUsertalkEditAllowed() );
878  $autoblock->mParentBlockId = $this->mId;
879  $autoblock->isSitewide( $this->isSitewide() );
880  $autoblock->setRestrictions( $this->getRestrictions() );
881 
882  if ( $this->getExpiry() == 'infinity' ) {
883  # Original block was indefinite, start an autoblock now
884  $autoblock->setExpiry( self::getAutoblockExpiry( $timestamp ) );
885  } else {
886  # If the user is already blocked with an expiry date, we don't
887  # want to pile on top of that.
888  $autoblock->setExpiry( min( $this->getExpiry(), self::getAutoblockExpiry( $timestamp ) ) );
889  }
890 
891  # Insert the block...
892  $status = $autoblock->insert();
893  return $status
894  ? $status['id']
895  : false;
896  }
897 
902  public function deleteIfExpired() {
903  if ( $this->isExpired() ) {
904  wfDebug( __METHOD__ . " -- deleting\n" );
905  $this->delete();
906  $retVal = true;
907  } else {
908  wfDebug( __METHOD__ . " -- not expired\n" );
909  $retVal = false;
910  }
911 
912  return $retVal;
913  }
914 
919  public function isExpired() {
920  $timestamp = wfTimestampNow();
921  wfDebug( __METHOD__ . " checking current " . $timestamp . " vs $this->mExpiry\n" );
922 
923  if ( !$this->getExpiry() ) {
924  return false;
925  } else {
926  return $timestamp > $this->getExpiry();
927  }
928  }
929 
936  public function isValid() {
937  wfDeprecated( __METHOD__, '1.33' );
938  return $this->getTarget() != null;
939  }
940 
944  public function updateTimestamp() {
945  if ( $this->mAuto ) {
946  $this->setTimestamp( wfTimestamp() );
947  $this->setExpiry( self::getAutoblockExpiry( $this->getTimestamp() ) );
948 
949  $dbw = wfGetDB( DB_MASTER );
950  $dbw->update( 'ipblocks',
951  [ /* SET */
952  'ipb_timestamp' => $dbw->timestamp( $this->getTimestamp() ),
953  'ipb_expiry' => $dbw->timestamp( $this->getExpiry() ),
954  ],
955  [ /* WHERE */
956  'ipb_id' => $this->getId(),
957  ],
958  __METHOD__
959  );
960  }
961  }
962 
968  public function getRangeStart() {
969  switch ( $this->type ) {
970  case self::TYPE_USER:
971  return '';
972  case self::TYPE_IP:
973  return IP::toHex( $this->target );
974  case self::TYPE_RANGE:
975  list( $start, /*...*/ ) = IP::parseRange( $this->target );
976  return $start;
977  default:
978  throw new MWException( "Block with invalid type" );
979  }
980  }
981 
987  public function getRangeEnd() {
988  switch ( $this->type ) {
989  case self::TYPE_USER:
990  return '';
991  case self::TYPE_IP:
992  return IP::toHex( $this->target );
993  case self::TYPE_RANGE:
994  list( /*...*/, $end ) = IP::parseRange( $this->target );
995  return $end;
996  default:
997  throw new MWException( "Block with invalid type" );
998  }
999  }
1000 
1005  public function getReason() {
1006  if ( $this->getType() === self::TYPE_AUTO ) {
1007  return $this->reason->message->inContentLanguage()->plain();
1008  }
1009  return $this->reason->text;
1010  }
1011 
1015  public function getId() {
1016  return $this->mId;
1017  }
1018 
1025  private function setId( $blockId ) {
1026  $this->mId = (int)$blockId;
1027 
1028  if ( is_array( $this->restrictions ) ) {
1029  $this->restrictions = $this->getBlockRestrictionStore()->setBlockId(
1030  $blockId, $this->restrictions
1031  );
1032  }
1033 
1034  return $this;
1035  }
1036 
1041  public function getParentBlockId() {
1042  return $this->mParentBlockId;
1043  }
1044 
1051  public function fromMaster( $x = null ) {
1052  return wfSetVar( $this->mFromMaster, $x );
1053  }
1054 
1060  public function isHardblock( $x = null ) {
1061  wfSetVar( $this->isHardblock, $x );
1062 
1063  # You can't *not* hardblock a user
1064  return $this->getType() == self::TYPE_USER
1065  ? true
1067  }
1068 
1073  public function isAutoblocking( $x = null ) {
1074  wfSetVar( $this->isAutoblocking, $x );
1075 
1076  # You can't put an autoblock on an IP or range as we don't have any history to
1077  # look over to get more IPs from
1078  return $this->getType() == self::TYPE_USER
1079  ? $this->isAutoblocking
1080  : false;
1081  }
1082 
1087  public function getRedactedName() {
1088  if ( $this->mAuto ) {
1089  return Html::element(
1090  'span',
1091  [ 'class' => 'mw-autoblockid' ],
1092  wfMessage( 'autoblockid', $this->mId )->text()
1093  );
1094  } else {
1095  return htmlspecialchars( $this->getTarget() );
1096  }
1097  }
1098 
1105  public static function getAutoblockExpiry( $timestamp ) {
1106  global $wgAutoblockExpiry;
1107 
1108  return wfTimestamp( TS_MW, wfTimestamp( TS_UNIX, $timestamp ) + $wgAutoblockExpiry );
1109  }
1110 
1114  public static function purgeExpired() {
1115  if ( wfReadOnly() ) {
1116  return;
1117  }
1118 
1120  wfGetDB( DB_MASTER ),
1121  __METHOD__,
1122  function ( IDatabase $dbw, $fname ) {
1123  $ids = $dbw->selectFieldValues( 'ipblocks',
1124  'ipb_id',
1125  [ 'ipb_expiry < ' . $dbw->addQuotes( $dbw->timestamp() ) ],
1126  $fname
1127  );
1128  if ( $ids ) {
1129  $blockRestrictionStore = MediaWikiServices::getInstance()->getBlockRestrictionStore();
1130  $blockRestrictionStore->deleteByBlockId( $ids );
1131 
1132  $dbw->delete( 'ipblocks', [ 'ipb_id' => $ids ], $fname );
1133  }
1134  }
1135  ) );
1136  }
1137 
1158  public static function newFromTarget( $specificTarget, $vagueTarget = null, $fromMaster = false ) {
1159  $blocks = self::newListFromTarget( $specificTarget, $vagueTarget, $fromMaster );
1160  return self::chooseMostSpecificBlock( $blocks );
1161  }
1162 
1172  public static function newListFromTarget(
1173  $specificTarget,
1174  $vagueTarget = null,
1175  $fromMaster = false
1176  ) {
1177  list( $target, $type ) = self::parseTarget( $specificTarget );
1178  if ( $type == self::TYPE_ID || $type == self::TYPE_AUTO ) {
1179  $block = self::newFromID( $target );
1180  return $block ? [ $block ] : [];
1181  } elseif ( $target === null && $vagueTarget == '' ) {
1182  # We're not going to find anything useful here
1183  # Be aware that the == '' check is explicit, since empty values will be
1184  # passed by some callers (T31116)
1185  return [];
1186  } elseif ( in_array(
1187  $type,
1188  [ self::TYPE_USER, self::TYPE_IP, self::TYPE_RANGE, null ] )
1189  ) {
1190  return self::newLoad( $target, $type, $fromMaster, $vagueTarget );
1191  }
1192  return [];
1193  }
1194 
1205  public static function getBlocksForIPList( array $ipChain, $isAnon, $fromMaster = false ) {
1206  if ( $ipChain === [] ) {
1207  return [];
1208  }
1209 
1210  $conds = [];
1211  $proxyLookup = MediaWikiServices::getInstance()->getProxyLookup();
1212  foreach ( array_unique( $ipChain ) as $ipaddr ) {
1213  # Discard invalid IP addresses. Since XFF can be spoofed and we do not
1214  # necessarily trust the header given to us, make sure that we are only
1215  # checking for blocks on well-formatted IP addresses (IPv4 and IPv6).
1216  # Do not treat private IP spaces as special as it may be desirable for wikis
1217  # to block those IP ranges in order to stop misbehaving proxies that spoof XFF.
1218  if ( !IP::isValid( $ipaddr ) ) {
1219  continue;
1220  }
1221  # Don't check trusted IPs (includes local CDNs which will be in every request)
1222  if ( $proxyLookup->isTrustedProxy( $ipaddr ) ) {
1223  continue;
1224  }
1225  # Check both the original IP (to check against single blocks), as well as build
1226  # the clause to check for rangeblocks for the given IP.
1227  $conds['ipb_address'][] = $ipaddr;
1228  $conds[] = self::getRangeCond( IP::toHex( $ipaddr ) );
1229  }
1230 
1231  if ( $conds === [] ) {
1232  return [];
1233  }
1234 
1235  if ( $fromMaster ) {
1236  $db = wfGetDB( DB_MASTER );
1237  } else {
1238  $db = wfGetDB( DB_REPLICA );
1239  }
1240  $conds = $db->makeList( $conds, LIST_OR );
1241  if ( !$isAnon ) {
1242  $conds = [ $conds, 'ipb_anon_only' => 0 ];
1243  }
1244  $blockQuery = self::getQueryInfo();
1245  $rows = $db->select(
1246  $blockQuery['tables'],
1247  array_merge( [ 'ipb_range_start', 'ipb_range_end' ], $blockQuery['fields'] ),
1248  $conds,
1249  __METHOD__,
1250  [],
1251  $blockQuery['joins']
1252  );
1253 
1254  $blocks = [];
1255  foreach ( $rows as $row ) {
1256  $block = self::newFromRow( $row );
1257  if ( !$block->isExpired() ) {
1258  $blocks[] = $block;
1259  }
1260  }
1261 
1262  return $blocks;
1263  }
1264 
1286  public static function chooseBlock( array $blocks, array $ipChain ) {
1287  if ( $blocks === [] ) {
1288  return null;
1289  } elseif ( count( $blocks ) == 1 ) {
1290  return $blocks[0];
1291  }
1292 
1293  // Sort hard blocks before soft ones and secondarily sort blocks
1294  // that disable account creation before those that don't.
1295  usort( $blocks, function ( DatabaseBlock $a, DatabaseBlock $b ) {
1296  $aWeight = (int)$a->isHardblock() . (int)$a->appliesToRight( 'createaccount' );
1297  $bWeight = (int)$b->isHardblock() . (int)$b->appliesToRight( 'createaccount' );
1298  return strcmp( $bWeight, $aWeight ); // highest weight first
1299  } );
1300 
1301  $blocksListExact = [
1302  'hard' => false,
1303  'disable_create' => false,
1304  'other' => false,
1305  'auto' => false
1306  ];
1307  $blocksListRange = [
1308  'hard' => false,
1309  'disable_create' => false,
1310  'other' => false,
1311  'auto' => false
1312  ];
1313  $ipChain = array_reverse( $ipChain );
1314 
1315  foreach ( $blocks as $block ) {
1316  // Stop searching if we have already have a "better" block. This
1317  // is why the order of the blocks matters
1318  if ( !$block->isHardblock() && $blocksListExact['hard'] ) {
1319  break;
1320  } elseif ( !$block->appliesToRight( 'createaccount' ) && $blocksListExact['disable_create'] ) {
1321  break;
1322  }
1323 
1324  foreach ( $ipChain as $checkip ) {
1325  $checkipHex = IP::toHex( $checkip );
1326  if ( (string)$block->getTarget() === $checkip ) {
1327  if ( $block->isHardblock() ) {
1328  $blocksListExact['hard'] = $blocksListExact['hard'] ?: $block;
1329  } elseif ( $block->appliesToRight( 'createaccount' ) ) {
1330  $blocksListExact['disable_create'] = $blocksListExact['disable_create'] ?: $block;
1331  } elseif ( $block->mAuto ) {
1332  $blocksListExact['auto'] = $blocksListExact['auto'] ?: $block;
1333  } else {
1334  $blocksListExact['other'] = $blocksListExact['other'] ?: $block;
1335  }
1336  // We found closest exact match in the ip list, so go to the next block
1337  break;
1338  } elseif ( array_filter( $blocksListExact ) == []
1339  && $block->getRangeStart() <= $checkipHex
1340  && $block->getRangeEnd() >= $checkipHex
1341  ) {
1342  if ( $block->isHardblock() ) {
1343  $blocksListRange['hard'] = $blocksListRange['hard'] ?: $block;
1344  } elseif ( $block->appliesToRight( 'createaccount' ) ) {
1345  $blocksListRange['disable_create'] = $blocksListRange['disable_create'] ?: $block;
1346  } elseif ( $block->mAuto ) {
1347  $blocksListRange['auto'] = $blocksListRange['auto'] ?: $block;
1348  } else {
1349  $blocksListRange['other'] = $blocksListRange['other'] ?: $block;
1350  }
1351  break;
1352  }
1353  }
1354  }
1355 
1356  if ( array_filter( $blocksListExact ) == [] ) {
1357  $blocksList = &$blocksListRange;
1358  } else {
1359  $blocksList = &$blocksListExact;
1360  }
1361 
1362  $chosenBlock = null;
1363  if ( $blocksList['hard'] ) {
1364  $chosenBlock = $blocksList['hard'];
1365  } elseif ( $blocksList['disable_create'] ) {
1366  $chosenBlock = $blocksList['disable_create'];
1367  } elseif ( $blocksList['other'] ) {
1368  $chosenBlock = $blocksList['other'];
1369  } elseif ( $blocksList['auto'] ) {
1370  $chosenBlock = $blocksList['auto'];
1371  } else {
1372  throw new MWException( "Proxy block found, but couldn't be classified." );
1373  }
1374 
1375  return $chosenBlock;
1376  }
1377 
1384  public function getType() {
1385  return $this->mAuto
1386  ? self::TYPE_AUTO
1387  : parent::getType();
1388  }
1389 
1398  public function setCookie( WebResponse $response ) {
1399  MediaWikiServices::getInstance()->getBlockManager()->setBlockCookie( $this, $response );
1400  }
1401 
1409  public static function clearCookie( WebResponse $response ) {
1410  MediaWikiServices::getInstance()->getBlockManager()->clearBlockCookie( $response );
1411  }
1412 
1423  public function getCookieValue() {
1424  return MediaWikiServices::getInstance()->getBlockManager()->getCookieValue( $this );
1425  }
1426 
1436  public static function getIdFromCookieValue( $cookieValue ) {
1437  return MediaWikiServices::getInstance()->getBlockManager()->getIdFromCookieValue( $cookieValue );
1438  }
1439 
1443  public function getIdentifier() {
1444  return $this->getId();
1445  }
1446 
1456  public function getRestrictions() {
1457  if ( $this->restrictions === null ) {
1458  // If the block id has not been set, then do not attempt to load the
1459  // restrictions.
1460  if ( !$this->mId ) {
1461  return [];
1462  }
1463  $this->restrictions = $this->getBlockRestrictionStore()->loadByBlockId( $this->mId );
1464  }
1465 
1466  return $this->restrictions;
1467  }
1468 
1476  public function setRestrictions( array $restrictions ) {
1477  $this->restrictions = array_filter( $restrictions, function ( $restriction ) {
1478  return $restriction instanceof Restriction;
1479  } );
1480 
1481  return $this;
1482  }
1483 
1487  public function appliesToTitle( Title $title ) {
1488  if ( $this->isSitewide() ) {
1489  return true;
1490  }
1491 
1492  $restrictions = $this->getRestrictions();
1493  foreach ( $restrictions as $restriction ) {
1494  if ( $restriction->matches( $title ) ) {
1495  return true;
1496  }
1497  }
1498 
1499  return false;
1500  }
1501 
1505  public function appliesToNamespace( $ns ) {
1506  if ( $this->isSitewide() ) {
1507  return true;
1508  }
1509 
1510  // Blocks do not apply to virtual namespaces.
1511  if ( $ns < 0 ) {
1512  return false;
1513  }
1514 
1515  $restriction = $this->findRestriction( NamespaceRestriction::TYPE, $ns );
1516 
1517  return (bool)$restriction;
1518  }
1519 
1523  public function appliesToPage( $pageId ) {
1524  if ( $this->isSitewide() ) {
1525  return true;
1526  }
1527 
1528  // If the pageId is not over zero, the block cannot apply to it.
1529  if ( $pageId <= 0 ) {
1530  return false;
1531  }
1532 
1533  $restriction = $this->findRestriction( PageRestriction::TYPE, $pageId );
1534 
1535  return (bool)$restriction;
1536  }
1537 
1545  private function findRestriction( $type, $value ) {
1546  $restrictions = $this->getRestrictions();
1547  foreach ( $restrictions as $restriction ) {
1548  if ( $restriction->getType() !== $type ) {
1549  continue;
1550  }
1551 
1552  if ( $restriction->getValue() === $value ) {
1553  return $restriction;
1554  }
1555  }
1556 
1557  return null;
1558  }
1559 
1565  public function shouldTrackWithCookie( $isAnon ) {
1566  wfDeprecated( __METHOD__, '1.34' );
1567  $config = RequestContext::getMain()->getConfig();
1568  switch ( $this->getType() ) {
1569  case self::TYPE_IP:
1570  case self::TYPE_RANGE:
1571  return $isAnon && $config->get( 'CookieSetOnIpBlock' );
1572  case self::TYPE_USER:
1573  return !$isAnon && $config->get( 'CookieSetOnAutoblock' ) && $this->isAutoblocking();
1574  default:
1575  return false;
1576  }
1577  }
1578 
1585  return MediaWikiServices::getInstance()->getBlockRestrictionStore();
1586  }
1587 
1591  public function getBy() {
1592  return ( $this->blocker ) ? $this->blocker->getId() : 0;
1593  }
1594 
1598  public function getByName() {
1599  return ( $this->blocker ) ? $this->blocker->getName() : '';
1600  }
1601 
1607  public function getBlocker() {
1608  return $this->blocker;
1609  }
1610 
1616  public function setBlocker( $user ) {
1617  if ( is_string( $user ) ) {
1618  $user = User::newFromName( $user, false );
1619  }
1620 
1621  if ( $user->isAnon() && User::isUsableName( $user->getName() ) ) {
1622  throw new \InvalidArgumentException(
1623  'Blocker must be a local user or a name that cannot be a local user'
1624  );
1625  }
1626 
1627  $this->blocker = $user;
1628  }
1629 }
1630 
1634 class_alias( DatabaseBlock::class, 'Block' );
insert(IDatabase $dbw=null)
Insert a block into the block table.
isUsertalkEditAllowed( $x=null)
Get or set the flag indicating whether this block blocks the target from editing their own user talk ...
Config $config
Definition: MediaWiki.php:39
static chooseBlock(array $blocks, array $ipChain)
From a list of multiple blocks, find the most exact and strongest block.
$response
initFromRow( $row)
Given a database row from the ipblocks table, initialize member variables.
static toHex( $ip)
Return a zero-padded upper case hexadecimal representation of an IP address.
Definition: IP.php:404
isCreateAccountBlocked( $x=null)
Get or set the flag indicating whether this block blocks the target from creating an account...
static element( $element, $attribs=[], $contents='')
Identical to rawElement(), but HTML-escapes $contents (like Xml::element()).
Definition: Html.php:231
getRangeStart()
Get the IP address at the start of the range in Hex form.
getDatabaseArray(IDatabase $dbw)
Get an array suitable for passing to $dbw->insert() or $dbw->update()
__construct(array $options=[])
Create a new block with specified option parameters on a user, IP or IP range.
static parseRange( $range)
Given a string range in a number of formats, return the start and end of the range in hexadecimal...
Definition: IP.php:500
$success
setBlocker( $user)
Set the user who implemented (or will implement) this block.
equals(DatabaseBlock $block)
Check if two blocks are effectively equal.
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
static newFromAnyId( $userId, $userName, $actorId, $dbDomain=false)
Static factory method for creation from an ID, name, and/or actor ID.
Definition: User.php:617
getAutoblockUpdateArray(IDatabase $dbw)
getCookieValue()
Get the BlockID cookie&#39;s value for this block.
deleteIfExpired()
Check if a block has expired.
A DatabaseBlock (unlike a SystemBlock) is stored in the database, may give rise to autoblocks and may...
static getInstance()
Returns the global default instance of the top level service locator.
const DB_MASTER
Definition: defines.php:26
get( $name)
Get a configuration variable such as "Sitename" or "UploadMaintenance.".
doRetroactiveAutoblock()
Retroactively autoblocks the last IP used by the user (if it is a user) blocked by this block...
timestamp( $ts=0)
Convert a timestamp in one of the formats accepted by ConvertibleTimestamp to the format used for ins...
getBlocker()
Get the user who implemented this block.
static getBlocksForIPList(array $ipChain, $isAnon, $fromMaster=false)
Get all blocks that match any IP from an array of IP addresses.
static defaultRetroactiveAutoblock(DatabaseBlock $block, array &$blockIds)
Retroactively autoblocks the last IP used by the user (if it is a user) blocked by this block...
The User object encapsulates all of the user-specific settings (user_id, name, rights, email address, options, last login time).
Definition: User.php:51
int $forcedTargetID
Hack for foreign blocking (CentralAuth)
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
$wgBlockCIDRLimit
Limits on the possible sizes of range blocks.
static isWhitelistedFromAutoblocks( $ip)
Checks whether a given IP is on the autoblock whitelist.
wfReadOnly()
Check whether the wiki is in read-only mode.
static newMigration()
Static constructor.
static getMain()
Get the RequestContext object associated with the main request.
const LIST_AND
Definition: Defines.php:39
setRestrictions(array $restrictions)
Set Restrictions.
isExpired()
Has the block expired?
getRangeEnd()
Get the IP address at the end of the range in Hex form.
isSitewide( $x=null)
Indicates that the block is a sitewide block.
fromMaster( $x=null)
Get/set a flag determining whether the master is used for reads.
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
$wgBlockDisablesLogin
If true, blocked users will not be allowed to login.
static isValid( $ip)
Validate an IP address.
Definition: IP.php:111
getRedactedName()
Get the block name, but with autoblocked IPs hidden as per standard privacy policy.
static getRangeCond( $start, $end=null)
Get a set of SQL conditions which will select rangeblocks encompassing a given range.
wfTimestampNow()
Convenience function; returns MediaWiki timestamp for the present time.
$wgPutIPinRC
Log IP addresses in the recentchanges table; can be accessed only by extensions (e.g.
$cache
Definition: mcc.php:33
encodeExpiry( $expiry)
Encode an expiry time into the DBMS dependent format.
static newLoad( $specificTarget, $specificType, $fromMaster, $vagueTarget=null)
Load blocks from the database which target the specific target exactly, or which cover the vague targ...
static isUsableName( $name)
Usernames which fail to pass this function will be blocked from user login and new account registrati...
Definition: User.php:1026
isEmailBlocked( $x=null)
Get or set the flag indicating whether this block blocks the target from sending emails.
static isInRange( $addr, $range)
Determine if a given IPv4/IPv6 address is in a given CIDR network.
Definition: IP.php:637
static purgeExpired()
Purge expired blocks from the ipblocks table.
static newFromRow( $row)
Create a new DatabaseBlock object from a database row.
getReasonComment()
Get the reason for creating the block.
appliesToRight( $right)
Determine whether the block prevents a given right.
getBlockRestrictionStore()
Get a BlockRestrictionStore instance.
static getIdFromCookieValue( $cookieValue)
Get the stored ID from the &#39;BlockID&#39; cookie.
const LIST_OR
Definition: Defines.php:42
getTimestamp()
Get the timestamp indicating when the block was created.
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...
setTimestamp( $timestamp)
Set the timestamp indicating when the block was created.
static isIPv6( $ip)
Given a string, determine if it as valid IP in IPv6 only.
Definition: IP.php:88
selectFieldValues( $table, $var, $cond='', $fname=__METHOD__, $options=[], $join_conds=[])
A SELECT wrapper which returns a list of single field values from result rows.
static newFromId( $id)
Static factory method for creation from a given user ID.
Definition: User.php:560
static addUpdate(DeferrableUpdate $update, $stage=self::POSTSEND)
Add an update to the deferred list to be run later by execute()
$lines
Definition: router.php:61
static getStore()
static getAutoblockExpiry( $timestamp)
Get a timestamp of the expiry for autoblocks.
Basic database interface for live and lazy-loaded relation database handles.
Definition: IDatabase.php:38
getId()
Get the user&#39;s ID.
Definition: User.php:2258
getHideName()
Get whether the block hides the target&#39;s username.
update()
Update a block in the DB with new parameters.
int null $type
AbstractBlock::TYPE_ constant.
static getQueryInfo()
Return the tables, fields, and join conditions to be selected to create a new block object...
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Throws a warning that $function is deprecated.
static clearCookie(WebResponse $response)
Unset the &#39;BlockID&#39; cookie.
isHardblock( $x=null)
Get/set whether the block is a hardblock (affects logged-in users on a given IP/range) ...
setHideName( $hideName)
Set whether ths block hides the target&#39;s username.
setId( $blockId)
Set the block ID.
setTarget( $target)
Set the target for this block, and update $this->type accordingly.
setExpiry( $expiry)
Set the block expiry time.
$line
Definition: mcc.php:119
getExpiry()
Get the block expiry time.
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:4430
getTarget()
Get the target for this particular block.
const DB_REPLICA
Definition: defines.php:25
getRestrictions()
Get Restrictions.
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
static newListFromTarget( $specificTarget, $vagueTarget=null, $fromMaster=false)
This is similar to DatabaseBlock::newFromTarget, but it returns all the relevant blocks.
static newFromID( $id)
Load a block from the block id.
static newFromName( $name, $validate='valid')
Static factory method for creation from username.
Definition: User.php:536
static getIpFragment( $hex)
Get the component of an IP address which is certain to be the same between an IP address and a rangeb...
doAutoblock( $autoblockIP)
Autoblocks the given IP, referring to this block.
isValid()
Is the block address valid (i.e.
delete( $table, $conds, $fname=__METHOD__)
DELETE query wrapper.
findRestriction( $type, $value)
Find Restriction by type and value.
setReason( $reason)
Set the reason for creating the block.
static parseCIDR( $range)
Convert a network specification in CIDR notation to an integer network and a number of bits...
Definition: IP.php:457
addQuotes( $s)
Escape and quote a raw value string for use in a SQL query.
static chooseMostSpecificBlock(array $blocks)
Choose the most specific block from some combination of user, IP and IP range blocks.
static newFromTarget( $specificTarget, $vagueTarget=null, $fromMaster=false)
Given a target and the target&#39;s type, get an existing block object if possible.
return true
Definition: router.php:92
setCookie(WebResponse $response)
Set the &#39;BlockID&#39; cookie to this block&#39;s ID and expiry time.
updateTimestamp()
Update the timestamp on autoblocks.
static run( $event, array $args=[], $deprecatedVersion=null)
Call hook functions defined in Hooks::register and $wgHooks.
Definition: Hooks.php:200
$wgAutoblockExpiry
Number of seconds before autoblock entries expire.