MediaWiki  master
DatabaseBlockStore.php
Go to the documentation of this file.
1 <?php
23 namespace MediaWiki\Block;
24 
26 use CommentStore;
27 use DeferredUpdates;
28 use InvalidArgumentException;
34 use MWException;
35 use Psr\Log\LoggerInterface;
36 use ReadOnlyMode;
37 use Wikimedia\Assert\Assert;
40 
47 
49  private $options;
50 
54  public const CONSTRUCTOR_OPTIONS = [
55  'PutIPinRC',
56  'BlockDisablesLogin',
57  ];
58 
60  private $logger;
61 
64 
67 
69  private $commentStore;
70 
72  private $hookRunner;
73 
75  private $loadBalancer;
76 
78  private $readOnlyMode;
79 
81  private $userFactory;
82 
94  public function __construct(
96  LoggerInterface $logger,
100  HookContainer $hookContainer,
104  ) {
105  $options->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS );
106 
107  $this->options = $options;
108  $this->logger = $logger;
109  $this->actorStoreFactory = $actorStoreFactory;
110  $this->blockRestrictionStore = $blockRestrictionStore;
111  $this->commentStore = $commentStore;
112  $this->hookRunner = new HookRunner( $hookContainer );
113  $this->loadBalancer = $loadBalancer;
114  $this->readOnlyMode = $readOnlyMode;
115  $this->userFactory = $userFactory;
116  }
117 
123  public function purgeExpiredBlocks() {
124  if ( $this->readOnlyMode->isReadOnly() ) {
125  return;
126  }
127 
128  $dbw = $this->loadBalancer->getConnectionRef( DB_PRIMARY );
130 
132  $dbw,
133  __METHOD__,
134  static function ( IDatabase $dbw, $fname ) use ( $blockRestrictionStore ) {
135  $ids = $dbw->selectFieldValues(
136  'ipblocks',
137  'ipb_id',
138  [ 'ipb_expiry < ' . $dbw->addQuotes( $dbw->timestamp() ) ],
139  $fname
140  );
141  if ( $ids ) {
143  $dbw->delete( 'ipblocks', [ 'ipb_id' => $ids ], $fname );
144  }
145  }
146  ) );
147  }
148 
156  private function checkDatabaseDomain( ?IDatabase $db, $expectedWiki ) {
157  if ( $db ) {
158  $dbDomain = $db->getDomainID();
159  $storeDomain = $this->loadBalancer->resolveDomainID( $expectedWiki );
160  if ( $dbDomain !== $storeDomain ) {
161  throw new InvalidArgumentException(
162  "DB connection domain '$dbDomain' does not match '$storeDomain'"
163  );
164  }
165  } else {
166  if ( $expectedWiki !== Block::LOCAL ) {
167  throw new InvalidArgumentException(
168  "Must provide a database connection for wiki '$expectedWiki'."
169  );
170  }
171  }
172  }
173 
185  public function insertBlock(
186  DatabaseBlock $block,
187  IDatabase $database = null
188  ) {
189  if ( !$block->getBlocker() || $block->getBlocker()->getName() === '' ) {
190  throw new MWException( 'Cannot insert a block without a blocker set' );
191  }
192 
193  $this->checkDatabaseDomain( $database, $block->getWikiId() );
194 
195  $this->logger->debug( 'Inserting block; timestamp ' . $block->getTimestamp() );
196 
197  // TODO T258866 - consider passing the database
198  $this->purgeExpiredBlocks();
199 
200  $dbw = $database ?: $this->loadBalancer->getConnectionRef( DB_PRIMARY );
201  $row = $this->getArrayForDatabaseBlock( $block, $dbw );
202 
203  $dbw->insert( 'ipblocks', $row, __METHOD__, [ 'IGNORE' ] );
204  $affected = $dbw->affectedRows();
205 
206  if ( $affected ) {
207  $block->setId( $dbw->insertId() );
208  if ( $block->getRawRestrictions() ) {
209  $this->blockRestrictionStore->insert( $block->getRawRestrictions() );
210  }
211  }
212 
213  // Don't collide with expired blocks.
214  // Do this after trying to insert to avoid locking.
215  if ( !$affected ) {
216  // T96428: The ipb_address index uses a prefix on a field, so
217  // use a standard SELECT + DELETE to avoid annoying gap locks.
218  $ids = $dbw->selectFieldValues(
219  'ipblocks',
220  'ipb_id',
221  [
222  'ipb_address' => $row['ipb_address'],
223  'ipb_user' => $row['ipb_user'],
224  'ipb_expiry < ' . $dbw->addQuotes( $dbw->timestamp() )
225  ],
226  __METHOD__
227  );
228  if ( $ids ) {
229  $dbw->delete( 'ipblocks', [ 'ipb_id' => $ids ], __METHOD__ );
230  $this->blockRestrictionStore->deleteByBlockId( $ids );
231  $dbw->insert( 'ipblocks', $row, __METHOD__, [ 'IGNORE' ] );
232  $affected = $dbw->affectedRows();
233  $block->setId( $dbw->insertId() );
234  if ( $block->getRawRestrictions() ) {
235  $this->blockRestrictionStore->insert( $block->getRawRestrictions() );
236  }
237  }
238  }
239 
240  if ( $affected ) {
241  $autoBlockIds = $this->doRetroactiveAutoblock( $block );
242 
243  if ( $this->options->get( 'BlockDisablesLogin' ) ) {
244  $targetUserIdentity = $block->getTargetUserIdentity();
245  if ( $targetUserIdentity ) {
246  $targetUser = $this->userFactory->newFromUserIdentity( $targetUserIdentity );
247  // Change user login token to force them to be logged out.
248  $targetUser->setToken();
249  $targetUser->saveSettings();
250  }
251  }
252 
253  return [ 'id' => $block->getId(), 'autoIds' => $autoBlockIds ];
254  }
255 
256  return false;
257  }
258 
267  public function updateBlock( DatabaseBlock $block ) {
268  $this->logger->debug( 'Updating block; timestamp ' . $block->getTimestamp() );
269 
270  // We could allow cross-wiki updates here, just like we do in insertBlock().
271  Assert::parameter(
272  $block->getWikiId() === Block::LOCAL,
273  '$block->getWikiId()',
274  'must belong to the local wiki.'
275  );
276 
277  $dbw = $this->loadBalancer->getConnectionRef( DB_PRIMARY );
278  $row = $this->getArrayForDatabaseBlock( $block, $dbw );
279  $dbw->startAtomic( __METHOD__ );
280 
281  $result = $dbw->update(
282  'ipblocks',
283  $row,
284  [ 'ipb_id' => $block->getId() ],
285  __METHOD__
286  );
287 
288  // Only update the restrictions if they have been modified.
289  $restrictions = $block->getRawRestrictions();
290  if ( $restrictions !== null ) {
291  // An empty array should remove all of the restrictions.
292  if ( empty( $restrictions ) ) {
293  $success = $this->blockRestrictionStore->deleteByBlockId( $block->getId() );
294  } else {
295  $success = $this->blockRestrictionStore->update( $restrictions );
296  }
297  // Update the result. The first false is the result, otherwise, true.
298  $result = $result && $success;
299  }
300 
301  if ( $block->isAutoblocking() ) {
302  // update corresponding autoblock(s) (T50813)
303  $dbw->update(
304  'ipblocks',
305  $this->getArrayForAutoblockUpdate( $block ),
306  [ 'ipb_parent_block_id' => $block->getId() ],
307  __METHOD__
308  );
309 
310  // Only update the restrictions if they have been modified.
311  if ( $restrictions !== null ) {
312  $this->blockRestrictionStore->updateByParentBlockId(
313  $block->getId(),
314  $restrictions
315  );
316  }
317  } else {
318  // autoblock no longer required, delete corresponding autoblock(s)
319  $this->blockRestrictionStore->deleteByParentBlockId( $block->getId() );
320  $dbw->delete(
321  'ipblocks',
322  [ 'ipb_parent_block_id' => $block->getId() ],
323  __METHOD__
324  );
325  }
326 
327  $dbw->endAtomic( __METHOD__ );
328 
329  if ( $result ) {
330  $autoBlockIds = $this->doRetroactiveAutoblock( $block );
331  return [ 'id' => $block->getId(), 'autoIds' => $autoBlockIds ];
332  }
333 
334  return false;
335  }
336 
344  public function deleteBlock( DatabaseBlock $block ): bool {
345  if ( $this->readOnlyMode->isReadOnly() ) {
346  return false;
347  }
348 
349  $blockId = $block->getId();
350 
351  if ( !$blockId ) {
352  throw new MWException(
353  __METHOD__ . " requires that a block id be set\n"
354  );
355  }
356  $dbw = $this->loadBalancer->getConnectionRef( DB_PRIMARY );
357 
358  $this->blockRestrictionStore->deleteByParentBlockId( $blockId );
359  $dbw->delete(
360  'ipblocks',
361  [ 'ipb_parent_block_id' => $blockId ],
362  __METHOD__
363  );
364 
365  $this->blockRestrictionStore->deleteByBlockId( $blockId );
366  $dbw->delete(
367  'ipblocks',
368  [ 'ipb_id' => $blockId ],
369  __METHOD__
370  );
371 
372  return $dbw->affectedRows() > 0;
373  }
374 
383  private function getArrayForDatabaseBlock(
384  DatabaseBlock $block,
385  IDatabase $dbw
386  ): array {
387  $expiry = $dbw->encodeExpiry( $block->getExpiry() );
388 
389  if ( $block->getTargetUserIdentity() ) {
390  $userId = $block->getTargetUserIdentity()->getId( $block->getWikiId() );
391  } else {
392  $userId = 0;
393  }
394  if ( !$block->getBlocker() ) {
395  throw new \RuntimeException( __METHOD__ . ': this block does not have a blocker' );
396  }
397  // DatabaseBlockStore supports inserting cross-wiki blocks by passing non-local IDatabase and blocker.
398  $blockerActor = $this->actorStoreFactory
399  ->getActorStore( $dbw->getDomainID() )
400  ->acquireActorId( $block->getBlocker(), $dbw );
401 
402  $blockArray = [
403  'ipb_address' => $block->getTargetName(),
404  'ipb_user' => $userId,
405  'ipb_by_actor' => $blockerActor,
406  'ipb_timestamp' => $dbw->timestamp( $block->getTimestamp() ),
407  'ipb_auto' => $block->getType() === AbstractBlock::TYPE_AUTO,
408  'ipb_anon_only' => !$block->isHardblock(),
409  'ipb_create_account' => $block->isCreateAccountBlocked(),
410  'ipb_enable_autoblock' => $block->isAutoblocking(),
411  'ipb_expiry' => $expiry,
412  'ipb_range_start' => $block->getRangeStart(),
413  'ipb_range_end' => $block->getRangeEnd(),
414  'ipb_deleted' => intval( $block->getHideName() ), // typecast required for SQLite
415  'ipb_block_email' => $block->isEmailBlocked(),
416  'ipb_allow_usertalk' => $block->isUsertalkEditAllowed(),
417  'ipb_parent_block_id' => $block->getParentBlockId(),
418  'ipb_sitewide' => $block->isSitewide(),
419  ];
420  $commentArray = $this->commentStore->insert(
421  $dbw,
422  'ipb_reason',
423  $block->getReasonComment()
424  );
425 
426  $combinedArray = $blockArray + $commentArray;
427  return $combinedArray;
428  }
429 
436  private function getArrayForAutoblockUpdate( DatabaseBlock $block ): array {
437  if ( !$block->getBlocker() ) {
438  throw new \RuntimeException( __METHOD__ . ': this block does not have a blocker' );
439  }
440  $dbw = $this->loadBalancer->getConnectionRef( DB_PRIMARY );
441  $blockerActor = $this->actorStoreFactory
442  ->getActorNormalization()
443  ->acquireActorId( $block->getBlocker(), $dbw );
444  $blockArray = [
445  'ipb_by_actor' => $blockerActor,
446  'ipb_create_account' => $block->isCreateAccountBlocked(),
447  'ipb_deleted' => (int)$block->getHideName(), // typecast required for SQLite
448  'ipb_allow_usertalk' => $block->isUsertalkEditAllowed(),
449  'ipb_sitewide' => $block->isSitewide(),
450  ];
451 
452  $commentArray = $this->commentStore->insert(
453  $dbw,
454  'ipb_reason',
455  $block->getReasonComment()
456  );
457 
458  $combinedArray = $blockArray + $commentArray;
459  return $combinedArray;
460  }
461 
469  private function doRetroactiveAutoblock( DatabaseBlock $block ): array {
470  $autoBlockIds = [];
471  // If autoblock is enabled, autoblock the LAST IP(s) used
472  if ( $block->isAutoblocking() && $block->getType() == AbstractBlock::TYPE_USER ) {
473  $this->logger->debug(
474  'Doing retroactive autoblocks for ' . $block->getTargetName()
475  );
476 
477  $hookAutoBlocked = [];
478  $continue = $this->hookRunner->onPerformRetroactiveAutoblock(
479  $block,
480  $hookAutoBlocked
481  );
482 
483  if ( $continue ) {
484  $coreAutoBlocked = $this->performRetroactiveAutoblock( $block );
485  $autoBlockIds = array_merge( $hookAutoBlocked, $coreAutoBlocked );
486  } else {
487  $autoBlockIds = $hookAutoBlocked;
488  }
489  }
490  return $autoBlockIds;
491  }
492 
500  private function performRetroactiveAutoblock( DatabaseBlock $block ): array {
501  if ( !$this->options->get( 'PutIPinRC' ) ) {
502  // No IPs in the recent changes table to autoblock
503  return [];
504  }
505 
506  $type = $block->getType();
507  if ( $type !== AbstractBlock::TYPE_USER ) {
508  // Autoblocks only apply to users
509  return [];
510  }
511 
512  $dbr = $this->loadBalancer->getConnectionRef( DB_REPLICA );
513 
514  $targetUser = $block->getTargetUserIdentity();
515  $actor = $targetUser ? $this->actorStoreFactory
516  ->getActorNormalization( $block->getWikiId() )
517  ->findActorId( $targetUser, $dbr ) : null;
518 
519  if ( !$actor ) {
520  $this->logger->debug( 'No actor found to retroactively autoblock' );
521  return [];
522  }
523 
524  $rcIp = $dbr->selectField(
525  [ 'recentchanges' ],
526  'rc_ip',
527  [ 'rc_actor' => $actor ],
528  __METHOD__,
529  [ 'ORDER BY' => 'rc_timestamp DESC' ]
530  );
531 
532  if ( !$rcIp ) {
533  $this->logger->debug( 'No IP found to retroactively autoblock' );
534  return [];
535  }
536 
537  $id = $block->doAutoblock( $rcIp );
538  if ( !$id ) {
539  return [];
540  }
541  return [ $id ];
542  }
543 
544 }
MediaWiki\Block\DatabaseBlockStore\$hookRunner
HookRunner $hookRunner
Definition: DatabaseBlockStore.php:72
MediaWiki\Block\DatabaseBlockStore\$blockRestrictionStore
BlockRestrictionStore $blockRestrictionStore
Definition: DatabaseBlockStore.php:66
MediaWiki\Block
Definition: AbstractBlock.php:21
MediaWiki\Block\DatabaseBlockStore\$logger
LoggerInterface $logger
Definition: DatabaseBlockStore.php:60
MediaWiki\Block\AbstractBlock\getTargetName
getTargetName()
Definition: AbstractBlock.php:332
if
if(ini_get( 'mbstring.func_overload')) if(!defined('MW_ENTRY_POINT'))
Pre-config setup: Before loading LocalSettings.php.
Definition: Setup.php:92
AutoCommitUpdate
Deferrable Update for closure/callback updates that should use auto-commit mode.
Definition: AutoCommitUpdate.php:9
MediaWiki\Block\DatabaseBlockStore\performRetroactiveAutoblock
performRetroactiveAutoblock(DatabaseBlock $block)
Actually retroactively autoblocks the last IP used by the user (if it is a user) blocked by this bloc...
Definition: DatabaseBlockStore.php:500
MediaWiki\Block\DatabaseBlock\getRangeStart
getRangeStart()
Get the IP address at the start of the range in Hex form.
Definition: DatabaseBlock.php:687
ReadOnlyMode
A service class for fetching the wiki's current read-only mode.
Definition: ReadOnlyMode.php:11
Wikimedia\Rdbms\IDatabase\encodeExpiry
encodeExpiry( $expiry)
Encode an expiry time into the DBMS dependent format.
MediaWiki\Block\DatabaseBlock\getType
getType()
Get the type of target for this particular block.int|null AbstractBlock::TYPE_ constant,...
Definition: DatabaseBlock.php:969
DeferredUpdates\addUpdate
static addUpdate(DeferrableUpdate $update, $stage=self::POSTSEND)
Add an update to the pending update queue for execution at the appropriate time.
Definition: DeferredUpdates.php:125
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:220
MediaWiki\Block\DatabaseBlock\getBlocker
getBlocker()
Get the user who implemented this block.
Definition: DatabaseBlock.php:1162
MediaWiki\Block\DatabaseBlockStore\$loadBalancer
ILoadBalancer $loadBalancer
Definition: DatabaseBlockStore.php:75
MediaWiki\Block\DatabaseBlockStore\getArrayForDatabaseBlock
getArrayForDatabaseBlock(DatabaseBlock $block, IDatabase $dbw)
Get an array suitable for passing to $dbw->insert() or $dbw->update()
Definition: DatabaseBlockStore.php:383
CommentStore
Handle database storage of comments such as edit summaries and log reasons.
Definition: CommentStore.php:42
MediaWiki\Block\DatabaseBlockStore\__construct
__construct(ServiceOptions $options, LoggerInterface $logger, ActorStoreFactory $actorStoreFactory, BlockRestrictionStore $blockRestrictionStore, CommentStore $commentStore, HookContainer $hookContainer, ILoadBalancer $loadBalancer, ReadOnlyMode $readOnlyMode, UserFactory $userFactory)
Definition: DatabaseBlockStore.php:94
MediaWiki\Block\AbstractBlock\getWikiId
getWikiId()
Definition: AbstractBlock.php:418
MediaWiki\Block\DatabaseBlockStore\purgeExpiredBlocks
purgeExpiredBlocks()
Delete expired blocks from the ipblocks table.
Definition: DatabaseBlockStore.php:123
MediaWiki\Block\DatabaseBlockStore\$commentStore
CommentStore $commentStore
Definition: DatabaseBlockStore.php:69
$success
$success
Definition: NoLocalSettings.php:42
MediaWiki\Block\DatabaseBlockStore
Definition: DatabaseBlockStore.php:46
MediaWiki\User\ActorStoreFactory
Definition: ActorStoreFactory.php:35
MediaWiki\Block\DatabaseBlock\getRawRestrictions
getRawRestrictions()
Get restrictions without loading from database if not yet loaded.
Definition: DatabaseBlock.php:1008
MediaWiki\Block\DatabaseBlockStore\$options
ServiceOptions $options
Definition: DatabaseBlockStore.php:49
MediaWiki\Block\DatabaseBlockStore\updateBlock
updateBlock(DatabaseBlock $block)
Update a block in the DB with new parameters.
Definition: DatabaseBlockStore.php:267
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\Block\DatabaseBlockStore\$actorStoreFactory
ActorStoreFactory $actorStoreFactory
Definition: DatabaseBlockStore.php:63
MediaWiki\Block\DatabaseBlock
A DatabaseBlock (unlike a SystemBlock) is stored in the database, may give rise to autoblocks and may...
Definition: DatabaseBlock.php:51
Wikimedia\Rdbms\IDatabase\timestamp
timestamp( $ts=0)
Convert a timestamp in one of the formats accepted by ConvertibleTimestamp to the format used for ins...
MWException
MediaWiki exception.
Definition: MWException.php:29
MediaWiki\Config\ServiceOptions
A class for passing options to services.
Definition: ServiceOptions.php:27
MediaWiki\Block\DatabaseBlockStore\CONSTRUCTOR_OPTIONS
const CONSTRUCTOR_OPTIONS
Definition: DatabaseBlockStore.php:54
DeferredUpdates
Class for managing the deferral of updates within the scope of a PHP script invocation.
Definition: DeferredUpdates.php:83
MediaWiki\Block\DatabaseBlockStore\doRetroactiveAutoblock
doRetroactiveAutoblock(DatabaseBlock $block)
Handles retroactively autoblocking the last IP used by the user (if it is a user) blocked by an auto ...
Definition: DatabaseBlockStore.php:469
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:233
MediaWiki\Block\AbstractBlock\getReasonComment
getReasonComment()
Get the reason for creating the block.
Definition: AbstractBlock.php:164
MediaWiki\Block\DatabaseBlock\getRangeEnd
getRangeEnd()
Get the IP address at the end of the range in Hex form.
Definition: DatabaseBlock.php:706
MediaWiki\Block\DatabaseBlockStore\getArrayForAutoblockUpdate
getArrayForAutoblockUpdate(DatabaseBlock $block)
Get an array suitable for autoblock updates.
Definition: DatabaseBlockStore.php:436
MediaWiki\Block\DatabaseBlock\getId
getId( $wikiId=self::LOCAL)
Get the block ID.(since 1.38) ?int
Definition: DatabaseBlock.php:734
DB_REPLICA
const DB_REPLICA
Definition: defines.php:25
MediaWiki\Block\AbstractBlock\isSitewide
isSitewide( $x=null)
Indicates that the block is a sitewide block.
Definition: AbstractBlock.php:207
MediaWiki\Block\DatabaseBlock\isAutoblocking
isAutoblocking( $x=null)
Definition: DatabaseBlock.php:785
MediaWiki\Block\DatabaseBlock\getParentBlockId
getParentBlockId()
Definition: DatabaseBlock.php:763
DB_PRIMARY
const DB_PRIMARY
Definition: defines.php:27
Wikimedia\Rdbms\IDatabase\getDomainID
getDomainID()
Return the currently selected domain ID.
MediaWiki\Block\DatabaseBlockStore\insertBlock
insertBlock(DatabaseBlock $block, IDatabase $database=null)
Insert a block into the block table.
Definition: DatabaseBlockStore.php:185
MediaWiki\Block\AbstractBlock\getExpiry
getExpiry()
Get the block expiry time.
Definition: AbstractBlock.php:358
MediaWiki\Block\Block\TYPE_AUTO
const TYPE_AUTO
Definition: Block.php:47
MediaWiki\Block\Block\TYPE_USER
const TYPE_USER
Definition: Block.php:44
MediaWiki\Block\AbstractBlock\getTimestamp
getTimestamp()
Get the timestamp indicating when the block was created.
Definition: AbstractBlock.php:379
MediaWiki\Block\DatabaseBlock\setId
setId( $blockId)
Set the block ID.
Definition: DatabaseBlock.php:747
Wikimedia\Rdbms\IDatabase\addQuotes
addQuotes( $s)
Escape and quote a raw value string for use in a SQL query.
MediaWiki\Block\DatabaseBlockStore\checkDatabaseDomain
checkDatabaseDomain(?IDatabase $db, $expectedWiki)
Throws an exception if the given database connection does not match the given wiki ID.
Definition: DatabaseBlockStore.php:156
Wikimedia\Rdbms\IDatabase\selectFieldValues
selectFieldValues( $table, $var, $cond='', $fname=__METHOD__, $options=[], $join_conds=[])
A SELECT wrapper which returns a list of single field values from result rows.
MediaWiki\Block\BlockRestrictionStore\deleteByBlockId
deleteByBlockId( $blockId)
Delete the restrictions by block ID.
Definition: BlockRestrictionStore.php:275
MediaWiki\Block\DatabaseBlock\doAutoblock
doAutoblock( $autoblockIP)
Autoblocks the given IP, referring to this block.
Definition: DatabaseBlock.php:574
MediaWiki\Block\AbstractBlock\getTargetUserIdentity
getTargetUserIdentity()
Definition: AbstractBlock.php:324
MediaWiki\HookContainer\HookContainer
HookContainer class.
Definition: HookContainer.php:45
MediaWiki\Block\AbstractBlock\getHideName
getHideName()
Get whether the block hides the target's username.
Definition: AbstractBlock.php:184
MediaWiki\HookContainer\HookRunner
This class provides an implementation of the core hook interfaces, forwarding hook calls to HookConta...
Definition: HookRunner.php:557
MediaWiki\Block\DatabaseBlockStore\deleteBlock
deleteBlock(DatabaseBlock $block)
Delete a DatabaseBlock from the database.
Definition: DatabaseBlockStore.php:344
MediaWiki\Block\DatabaseBlockStore\$readOnlyMode
ReadOnlyMode $readOnlyMode
Definition: DatabaseBlockStore.php:78
MediaWiki\Block\DatabaseBlockStore\$userFactory
UserFactory $userFactory
Definition: DatabaseBlockStore.php:81
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:772
MediaWiki\User\UserFactory
Creates User objects.
Definition: UserFactory.php:41
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:246
Wikimedia\Rdbms\IDatabase\delete
delete( $table, $conds, $fname=__METHOD__)
Delete all rows in a table that match a condition.
Wikimedia\Rdbms\ILoadBalancer
Database cluster connection, tracking, load balancing, and transaction manager interface.
Definition: ILoadBalancer.php:81
MediaWiki\Config\ServiceOptions\assertRequiredOptions
assertRequiredOptions(array $expectedKeys)
Assert that the list of options provided in this instance exactly match $expectedKeys,...
Definition: ServiceOptions.php:71
MediaWiki\Block\BlockRestrictionStore
Definition: BlockRestrictionStore.php:36
$type
$type
Definition: testCompression.php:52