Add block restriction classes
Partial blocks logic will be used in multiple places. This classes will group block restriction functionality to avoid code duplication Bug: T202036 Change-Id: I675316dddf272fd0d6172ecad3882160752bf780
This commit is contained in:
parent
6cd66511d2
commit
a562611e5b
13 changed files with 1698 additions and 7 deletions
|
|
@ -130,6 +130,7 @@ class AutoLoader {
|
|||
public static function getAutoloadNamespaces() {
|
||||
return [
|
||||
'MediaWiki\\Auth\\' => __DIR__ . '/auth/',
|
||||
'MediaWiki\\Block\\' => __DIR__ . '/block/',
|
||||
'MediaWiki\\Edit\\' => __DIR__ . '/edit/',
|
||||
'MediaWiki\\EditPage\\' => __DIR__ . '/editpage/',
|
||||
'MediaWiki\\Linker\\' => __DIR__ . '/linker/',
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@
|
|||
|
||||
use Wikimedia\Rdbms\Database;
|
||||
use Wikimedia\Rdbms\IDatabase;
|
||||
use MediaWiki\Block\BlockRestriction;
|
||||
use MediaWiki\Block\Restriction\Restriction;
|
||||
use MediaWiki\MediaWikiServices;
|
||||
|
||||
class Block {
|
||||
|
|
@ -79,6 +81,12 @@ class Block {
|
|||
/** @var string|null */
|
||||
private $systemBlockType;
|
||||
|
||||
/** @var bool */
|
||||
private $isSitewide;
|
||||
|
||||
/** @var Restriction[] */
|
||||
private $restrictions;
|
||||
|
||||
# TYPE constants
|
||||
const TYPE_USER = 1;
|
||||
const TYPE_IP = 2;
|
||||
|
|
@ -129,6 +137,7 @@ class Block {
|
|||
'allowUsertalk' => false,
|
||||
'byText' => '',
|
||||
'systemBlock' => null,
|
||||
'sitewide' => true,
|
||||
];
|
||||
|
||||
if ( func_num_args() > 1 || !is_array( $options ) ) {
|
||||
|
|
@ -165,6 +174,7 @@ class Block {
|
|||
$this->mHideName = (bool)$options['hideName'];
|
||||
$this->isHardblock( !$options['anonOnly'] );
|
||||
$this->isAutoblocking( (bool)$options['enableAutoblock'] );
|
||||
$this->isSitewide( (bool)$options['sitewide'] );
|
||||
|
||||
# Prevention measures
|
||||
$this->prevents( 'sendemail', (bool)$options['blockEmail'] );
|
||||
|
|
@ -236,6 +246,7 @@ class Block {
|
|||
'ipb_block_email',
|
||||
'ipb_allow_usertalk',
|
||||
'ipb_parent_block_id',
|
||||
'ipb_sitewide',
|
||||
] + CommentStore::getStore()->getFields( 'ipb_reason' );
|
||||
}
|
||||
|
||||
|
|
@ -266,6 +277,7 @@ class Block {
|
|||
'ipb_block_email',
|
||||
'ipb_allow_usertalk',
|
||||
'ipb_parent_block_id',
|
||||
'ipb_sitewide',
|
||||
] + $commentQuery['fields'] + $actorQuery['fields'],
|
||||
'joins' => $commentQuery['joins'] + $actorQuery['joins'],
|
||||
];
|
||||
|
|
@ -292,6 +304,10 @@ class Block {
|
|||
&& $this->prevents( 'sendemail' ) == $block->prevents( 'sendemail' )
|
||||
&& $this->prevents( 'editownusertalk' ) == $block->prevents( 'editownusertalk' )
|
||||
&& $this->mReason == $block->mReason
|
||||
&& $this->isSitewide() == $block->isSitewide()
|
||||
// Block::getRestrictions() may perform a database query, so keep it at
|
||||
// the end.
|
||||
&& BlockRestriction::equals( $this->getRestrictions(), $block->getRestrictions() )
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -477,6 +493,7 @@ class Block {
|
|||
|
||||
$this->isHardblock( !$row->ipb_anon_only );
|
||||
$this->isAutoblocking( $row->ipb_enable_autoblock );
|
||||
$this->isSitewide( (bool)$row->ipb_sitewide );
|
||||
|
||||
$this->prevents( 'createaccount', $row->ipb_create_account );
|
||||
$this->prevents( 'sendemail', $row->ipb_block_email );
|
||||
|
|
@ -510,7 +527,11 @@ class Block {
|
|||
}
|
||||
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
|
||||
BlockRestriction::deleteByParentBlockId( $this->getId() );
|
||||
$dbw->delete( 'ipblocks', [ 'ipb_parent_block_id' => $this->getId() ], __METHOD__ );
|
||||
|
||||
BlockRestriction::deleteByBlockId( $this->getId() );
|
||||
$dbw->delete( 'ipblocks', [ 'ipb_id' => $this->getId() ], __METHOD__ );
|
||||
|
||||
return $dbw->affectedRows() > 0;
|
||||
|
|
@ -546,7 +567,12 @@ class Block {
|
|||
|
||||
$dbw->insert( 'ipblocks', $row, __METHOD__, [ 'IGNORE' ] );
|
||||
$affected = $dbw->affectedRows();
|
||||
$this->mId = $dbw->insertId();
|
||||
if ( $affected ) {
|
||||
$this->setId( $dbw->insertId() );
|
||||
if ( $this->restrictions ) {
|
||||
BlockRestriction::insert( $this->restrictions );
|
||||
}
|
||||
}
|
||||
|
||||
# Don't collide with expired blocks.
|
||||
# Do this after trying to insert to avoid locking.
|
||||
|
|
@ -564,9 +590,13 @@ class Block {
|
|||
);
|
||||
if ( $ids ) {
|
||||
$dbw->delete( 'ipblocks', [ 'ipb_id' => $ids ], __METHOD__ );
|
||||
BlockRestriction::deleteByBlockId( $ids );
|
||||
$dbw->insert( 'ipblocks', $row, __METHOD__, [ 'IGNORE' ] );
|
||||
$affected = $dbw->affectedRows();
|
||||
$this->mId = $dbw->insertId();
|
||||
$this->setId( $dbw->insertId() );
|
||||
if ( $this->restrictions ) {
|
||||
BlockRestriction::insert( $this->restrictions );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -598,14 +628,24 @@ class Block {
|
|||
|
||||
$dbw->startAtomic( __METHOD__ );
|
||||
|
||||
$dbw->update(
|
||||
$result = $dbw->update(
|
||||
'ipblocks',
|
||||
$this->getDatabaseArray( $dbw ),
|
||||
[ 'ipb_id' => $this->getId() ],
|
||||
__METHOD__
|
||||
);
|
||||
|
||||
$affected = $dbw->affectedRows();
|
||||
// Only update the restrictions if they have been modified.
|
||||
if ( $this->restrictions !== null ) {
|
||||
// An empty array should remove all of the restrictions.
|
||||
if ( empty( $this->restrictions ) ) {
|
||||
$success = BlockRestriction::deleteByBlockId( $this->getId() );
|
||||
} else {
|
||||
$success = BlockRestriction::update( $this->restrictions );
|
||||
}
|
||||
// Update the result. The first false is the result, otherwise, true.
|
||||
$result = $result && $success;
|
||||
}
|
||||
|
||||
if ( $this->isAutoblocking() ) {
|
||||
// update corresponding autoblock(s) (T50813)
|
||||
|
|
@ -615,8 +655,14 @@ class Block {
|
|||
[ 'ipb_parent_block_id' => $this->getId() ],
|
||||
__METHOD__
|
||||
);
|
||||
|
||||
// Only update the restrictions if they have been modified.
|
||||
if ( $this->restrictions !== null ) {
|
||||
BlockRestriction::updateByParentBlockId( $this->getId(), $this->restrictions );
|
||||
}
|
||||
} else {
|
||||
// autoblock no longer required, delete corresponding autoblock(s)
|
||||
BlockRestriction::deleteByParentBlockId( $this->getId() );
|
||||
$dbw->delete(
|
||||
'ipblocks',
|
||||
[ 'ipb_parent_block_id' => $this->getId() ],
|
||||
|
|
@ -626,12 +672,12 @@ class Block {
|
|||
|
||||
$dbw->endAtomic( __METHOD__ );
|
||||
|
||||
if ( $affected ) {
|
||||
if ( $result ) {
|
||||
$auto_ipd_ids = $this->doRetroactiveAutoblock();
|
||||
return [ 'id' => $this->mId, 'autoIds' => $auto_ipd_ids ];
|
||||
}
|
||||
|
||||
return false;
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -662,7 +708,8 @@ class Block {
|
|||
'ipb_deleted' => intval( $this->mHideName ), // typecast required for SQLite
|
||||
'ipb_block_email' => $this->prevents( 'sendemail' ),
|
||||
'ipb_allow_usertalk' => !$this->prevents( 'editownusertalk' ),
|
||||
'ipb_parent_block_id' => $this->mParentBlockId
|
||||
'ipb_parent_block_id' => $this->mParentBlockId,
|
||||
'ipb_sitewide' => $this->isSitewide(),
|
||||
] + CommentStore::getStore()->insert( $dbw, 'ipb_reason', $this->mReason )
|
||||
+ ActorMigration::newMigration()->getInsertValues( $dbw, 'ipb_by', $this->getBlocker() );
|
||||
|
||||
|
|
@ -865,6 +912,8 @@ class Block {
|
|||
$autoblock->mHideName = $this->mHideName;
|
||||
$autoblock->prevents( 'editownusertalk', $this->prevents( 'editownusertalk' ) );
|
||||
$autoblock->mParentBlockId = $this->mId;
|
||||
$autoblock->isSitewide( $this->isSitewide() );
|
||||
$autoblock->setRestrictions( $this->getRestrictions() );
|
||||
|
||||
if ( $this->mExpiry == 'infinity' ) {
|
||||
# Original block was indefinite, start an autoblock now
|
||||
|
|
@ -1014,6 +1063,22 @@ class Block {
|
|||
return $this->mId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the block ID
|
||||
*
|
||||
* @param int $blockId
|
||||
* @return int
|
||||
*/
|
||||
private function setId( $blockId ) {
|
||||
$this->mId = (int)$blockId;
|
||||
|
||||
if ( is_array( $this->restrictions ) ) {
|
||||
$this->restrictions = BlockRestriction::setBlockId( $blockId, $this->restrictions );
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the system block type, if any
|
||||
* @since 1.29
|
||||
|
|
@ -1061,6 +1126,18 @@ class Block {
|
|||
: false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that the block is a sitewide block. This means the user is
|
||||
* prohibited from editing any page on the site (other than their own talk
|
||||
* page).
|
||||
*
|
||||
* @param null|bool $x
|
||||
* @return bool
|
||||
*/
|
||||
public function isSitewide( $x = null ) {
|
||||
return wfSetVar( $this->isSitewide, $x );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get/set whether the Block prevents a given action
|
||||
*
|
||||
|
|
@ -1145,6 +1222,7 @@ class Block {
|
|||
$fname
|
||||
);
|
||||
if ( $ids ) {
|
||||
BlockRestriction::deleteByBlockId( $ids );
|
||||
$dbw->delete( 'ipblocks', [ 'ipb_id' => $ids ], $fname );
|
||||
}
|
||||
}
|
||||
|
|
@ -1648,4 +1726,40 @@ class Block {
|
|||
$lang->userTimeAndDate( $this->mTimestamp, $context->getUser() ),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Restrictions.
|
||||
*
|
||||
* Getting the restrictions will perform a database query if the restrictions
|
||||
* are not already loaded.
|
||||
*
|
||||
* @return Restriction[]
|
||||
*/
|
||||
public function getRestrictions() {
|
||||
if ( $this->restrictions === null ) {
|
||||
// If the block id has not been set, then do not attempt to load the
|
||||
// restrictions.
|
||||
if ( !$this->mId ) {
|
||||
return [];
|
||||
}
|
||||
$this->restrictions = BlockRestriction::loadByBlockId( $this->mId );
|
||||
}
|
||||
|
||||
return $this->restrictions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Restrictions.
|
||||
*
|
||||
* @param Restriction[] $restrictions
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setRestrictions( array $restrictions ) {
|
||||
$this->restrictions = array_filter( $restrictions, function ( $restriction ) {
|
||||
return $restriction instanceof Restriction;
|
||||
} );
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9027,6 +9027,16 @@ $wgChangeTagsSchemaMigrationStage = MIGRATION_WRITE_BOTH;
|
|||
*/
|
||||
$wgTagStatisticsNewTable = false;
|
||||
|
||||
/**
|
||||
* Flag to enable Partial Blocks. This allows an admin to prevent a user from editing specific pages
|
||||
* or namespaces.
|
||||
*
|
||||
* @since 1.32
|
||||
* @deprecated 1.32
|
||||
* @var bool
|
||||
*/
|
||||
$wgEnablePartialBlocks = false;
|
||||
|
||||
/**
|
||||
* For really cool vim folding this needs to be at the end:
|
||||
* vim: foldmarker=@{,@} foldmethod=marker
|
||||
|
|
|
|||
417
includes/block/BlockRestriction.php
Normal file
417
includes/block/BlockRestriction.php
Normal file
|
|
@ -0,0 +1,417 @@
|
|||
<?php
|
||||
/**
|
||||
* Block restriction interface.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* @file
|
||||
*/
|
||||
|
||||
namespace MediaWiki\Block;
|
||||
|
||||
use MediaWiki\Block\Restriction\PageRestriction;
|
||||
use MediaWiki\Block\Restriction\Restriction;
|
||||
use Wikimedia\Rdbms\IResultWrapper;
|
||||
use Wikimedia\Rdbms\IDatabase;
|
||||
|
||||
class BlockRestriction {
|
||||
|
||||
/**
|
||||
* Retrieves the restrictions from the database by block id.
|
||||
*
|
||||
* @param int|array $blockId
|
||||
* @param IDatabase|null $db
|
||||
* @param array $options Options to pass to the select query.
|
||||
* @return Restriction[]
|
||||
*/
|
||||
public static function loadByBlockId( $blockId, IDatabase $db = null ) {
|
||||
if ( is_null( $blockId ) || $blockId === [] ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$db = $db ?: wfGetDb( DB_REPLICA );
|
||||
|
||||
$result = $db->select(
|
||||
[ 'ipblocks_restrictions', 'page' ],
|
||||
[ 'ir_ipb_id', 'ir_type', 'ir_value', 'page_namespace', 'page_title' ],
|
||||
[ 'ir_ipb_id' => $blockId ],
|
||||
__METHOD__,
|
||||
[],
|
||||
[ 'page' => [ 'LEFT JOIN', [ 'ir_type' => PageRestriction::TYPE_ID, 'ir_value=page_id' ] ] ]
|
||||
);
|
||||
|
||||
return self::resultToRestrictions( $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the restrictions into the database.
|
||||
*
|
||||
* @param Restriction[] $restrictions
|
||||
* @return bool
|
||||
*/
|
||||
public static function insert( array $restrictions ) {
|
||||
if ( empty( $restrictions ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$rows = [];
|
||||
foreach ( $restrictions as $restriction ) {
|
||||
if ( !$restriction instanceof Restriction ) {
|
||||
continue;
|
||||
}
|
||||
$rows[] = $restriction->toRow();
|
||||
}
|
||||
|
||||
if ( empty( $rows ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
|
||||
return $dbw->insert(
|
||||
'ipblocks_restrictions',
|
||||
$rows,
|
||||
__METHOD__,
|
||||
[ 'IGNORE' ]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the list of restrictions. This method does not allow removing all
|
||||
* of the restrictions. To do that, use ::deleteByBlockId().
|
||||
*
|
||||
* @param Restriction[] $restrictions
|
||||
* @return bool
|
||||
*/
|
||||
public static function update( array $restrictions ) {
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
|
||||
$dbw->startAtomic( __METHOD__ );
|
||||
|
||||
// Organize the restrictions by blockid.
|
||||
$restrictionList = self::restrictionsByBlockId( $restrictions );
|
||||
|
||||
// Load the existing restrictions and organize by block id. Any block ids
|
||||
// that were passed into this function will be used to load all of the
|
||||
// existing restrictions. This list might be the same, or may be completely
|
||||
// different.
|
||||
$existingList = [];
|
||||
$blockIds = array_keys( $restrictionList );
|
||||
if ( !empty( $blockIds ) ) {
|
||||
$result = $dbw->select(
|
||||
[ 'ipblocks_restrictions', 'page' ],
|
||||
[ 'ir_ipb_id', 'ir_type', 'ir_value' ],
|
||||
[ 'ir_ipb_id' => $blockIds ],
|
||||
__METHOD__,
|
||||
[ 'FOR UPDATE' ]
|
||||
);
|
||||
|
||||
$existingList = self::restrictionsByBlockId(
|
||||
self::resultToRestrictions( $result )
|
||||
);
|
||||
}
|
||||
|
||||
$result = true;
|
||||
// Perform the actions on a per block-id basis.
|
||||
foreach ( $restrictionList as $blockId => $blockRestrictions ) {
|
||||
// Insert all of the restrictions first, ignoring ones that already exist.
|
||||
$success = self::insert( $blockRestrictions );
|
||||
|
||||
// Update the result. The first false is the result, otherwise, true.
|
||||
$result = $success && $result;
|
||||
|
||||
$restrictionsToRemove = self::restrictionsToRemove(
|
||||
$existingList[$blockId] ?? [],
|
||||
$restrictions
|
||||
);
|
||||
|
||||
// Nothing to remove.
|
||||
if ( empty( $restrictionsToRemove ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$success = self::delete( $restrictionsToRemove );
|
||||
|
||||
// Update the result. The first false is the result, otherwise, true.
|
||||
$result = $success && $result;
|
||||
}
|
||||
|
||||
$dbw->endAtomic( __METHOD__ );
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the list of restrictions by parent id.
|
||||
*
|
||||
* @param int $parentBlockId
|
||||
* @param Restriction[] $restrictions
|
||||
* @return bool
|
||||
*/
|
||||
public static function updateByParentBlockId( $parentBlockId, array $restrictions ) {
|
||||
// If removing all of the restrictions, then just delete them all.
|
||||
if ( empty( $restrictions ) ) {
|
||||
return self::deleteByParentBlockId( $parentBlockId );
|
||||
}
|
||||
|
||||
$parentBlockId = (int)$parentBlockId;
|
||||
|
||||
$db = wfGetDb( DB_MASTER );
|
||||
|
||||
$db->startAtomic( __METHOD__ );
|
||||
|
||||
$blockIds = $db->selectFieldValues(
|
||||
'ipblocks',
|
||||
'ipb_id',
|
||||
[ 'ipb_parent_block_id' => $parentBlockId ],
|
||||
__METHOD__,
|
||||
[ 'FOR UPDATE' ]
|
||||
);
|
||||
|
||||
$result = true;
|
||||
foreach ( $blockIds as $id ) {
|
||||
$success = self::update( self::setBlockId( $id, $restrictions ) );
|
||||
// Update the result. The first false is the result, otherwise, true.
|
||||
$result = $success && $result;
|
||||
}
|
||||
|
||||
$db->endAtomic( __METHOD__ );
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the restrictions.
|
||||
*
|
||||
* @param Restriction[]|null $restrictions
|
||||
* @throws MWException
|
||||
* @return bool
|
||||
*/
|
||||
public static function delete( array $restrictions ) {
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$result = true;
|
||||
foreach ( $restrictions as $restriction ) {
|
||||
if ( !$restriction instanceof Restriction ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$success = $dbw->delete(
|
||||
'ipblocks_restrictions',
|
||||
// The restriction row is made up of a compound primary key. Therefore,
|
||||
// the row and the delete conditions are the same.
|
||||
$restriction->toRow(),
|
||||
__METHOD__
|
||||
);
|
||||
// Update the result. The first false is the result, otherwise, true.
|
||||
$result = $success && $result;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the restrictions by Block ID.
|
||||
*
|
||||
* @param int|array $blockId
|
||||
* @throws MWException
|
||||
* @return bool
|
||||
*/
|
||||
public static function deleteByBlockId( $blockId ) {
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
return $dbw->delete(
|
||||
'ipblocks_restrictions',
|
||||
[ 'ir_ipb_id' => $blockId ],
|
||||
__METHOD__
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the restrictions by Parent Block ID.
|
||||
*
|
||||
* @param int|array $parentBlockId
|
||||
* @throws MWException
|
||||
* @return bool
|
||||
*/
|
||||
public static function deleteByParentBlockId( $parentBlockId ) {
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
return $dbw->deleteJoin(
|
||||
'ipblocks_restrictions',
|
||||
'ipblocks',
|
||||
'ir_ipb_id',
|
||||
'ipb_id',
|
||||
[ 'ipb_parent_block_id' => $parentBlockId ],
|
||||
__METHOD__
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if two arrays of Restrictions are effectively equal. This is a loose
|
||||
* equality check as the restrictions do not have to contain the same block
|
||||
* ids.
|
||||
*
|
||||
* @param Restriction[] $a
|
||||
* @param Restriction[] $b
|
||||
* @return bool
|
||||
*/
|
||||
public static function equals( array $a, array $b ) {
|
||||
$filter = function ( $restriction ) {
|
||||
return $restriction instanceof Restriction;
|
||||
};
|
||||
|
||||
// Ensure that every item in the array is a Restriction. This prevents a
|
||||
// fatal error from calling Restriction::getHash if something in the array
|
||||
// is not a restriction.
|
||||
$a = array_filter( $a, $filter );
|
||||
$b = array_filter( $b, $filter );
|
||||
|
||||
$aCount = count( $a );
|
||||
$bCount = count( $b );
|
||||
|
||||
// If the count is different, then they are obviously a different set.
|
||||
if ( $aCount !== $bCount ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If both sets contain no items, then they are the same set.
|
||||
if ( $aCount === 0 && $bCount === 0 ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$hasher = function ( $r ) {
|
||||
return $r->getHash();
|
||||
};
|
||||
|
||||
$aHashes = array_map( $hasher, $a );
|
||||
$bHashes = array_map( $hasher, $b );
|
||||
|
||||
sort( $aHashes );
|
||||
sort( $bHashes );
|
||||
|
||||
return $aHashes === $bHashes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the blockId on a set of restrictions and return a new set.
|
||||
*
|
||||
* @param int $blockId
|
||||
* @param Restriction[] $restrictions
|
||||
* @return Restriction[]
|
||||
*/
|
||||
public static function setBlockId( $blockId, array $restrictions ) {
|
||||
$blockRestrictions = [];
|
||||
|
||||
foreach ( $restrictions as $restriction ) {
|
||||
if ( !$restriction instanceof Restriction ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Clone the restriction so any references to the current restriction are
|
||||
// not suddenly changed to a different blockId.
|
||||
$restriction = clone $restriction;
|
||||
$restriction->setBlockId( $blockId );
|
||||
|
||||
$blockRestrictions[] = $restriction;
|
||||
}
|
||||
|
||||
return $blockRestrictions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the restrictions that should be removed, which are existing
|
||||
* restrictions that are not in the new list of restrictions.
|
||||
*
|
||||
* @param Restriction[] $existing
|
||||
* @param Restriction[] $new
|
||||
* @return array
|
||||
*/
|
||||
private static function restrictionsToRemove( array $existing, array $new ) {
|
||||
return array_filter( $existing, function ( $e ) use ( $new ) {
|
||||
foreach ( $new as $restriction ) {
|
||||
if ( !$restriction instanceof Restriction ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( $restriction->equals( $e ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} );
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an array of restrictions to an associative array of restrictions
|
||||
* where the keys are the block ids.
|
||||
*
|
||||
* @param Restriction[] $restrictions
|
||||
* @return array
|
||||
*/
|
||||
private static function restrictionsByBlockId( array $restrictions ) {
|
||||
$blockRestrictions = [];
|
||||
|
||||
foreach ( $restrictions as $restriction ) {
|
||||
// Ensure that all of the items in the array are restrictions.
|
||||
if ( !$restriction instanceof Restriction ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( !isset( $blockRestrictions[$restriction->getBlockId()] ) ) {
|
||||
$blockRestrictions[$restriction->getBlockId()] = [];
|
||||
}
|
||||
|
||||
$blockRestrictions[$restriction->getBlockId()][] = $restriction;
|
||||
}
|
||||
|
||||
return $blockRestrictions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an Result Wrapper to an array of restrictions.
|
||||
*
|
||||
* @param IResultWrapper $result
|
||||
* @return Restriction[]
|
||||
*/
|
||||
private static function resultToRestrictions( IResultWrapper $result ) {
|
||||
$restrictions = [];
|
||||
foreach ( $result as $row ) {
|
||||
$restriction = self::rowToRestriction( $row );
|
||||
|
||||
if ( !$restriction ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$restrictions[] = $restriction;
|
||||
}
|
||||
|
||||
return $restrictions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a result row from the database into a restriction object.
|
||||
*
|
||||
* @param \stdClass $row
|
||||
* @return Restriction|null
|
||||
*/
|
||||
private static function rowToRestriction( \stdClass $row ) {
|
||||
switch ( $row->ir_type ) {
|
||||
case PageRestriction::TYPE_ID:
|
||||
return PageRestriction::newFromRow( $row );
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
102
includes/block/Restriction/AbstractRestriction.php
Normal file
102
includes/block/Restriction/AbstractRestriction.php
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
<?php
|
||||
/**
|
||||
* Abstract block restriction.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* @file
|
||||
*/
|
||||
|
||||
namespace MediaWiki\Block\Restriction;
|
||||
|
||||
abstract class AbstractRestriction implements Restriction {
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $blockId;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $value;
|
||||
|
||||
/**
|
||||
* Create Restriction.
|
||||
*
|
||||
* @param int $blockId
|
||||
* @param int $value
|
||||
*/
|
||||
public function __construct( $blockId, $value ) {
|
||||
$this->blockId = (int)$blockId;
|
||||
$this->value = (int)$value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getBlockId() {
|
||||
return $this->blockId;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setBlockId( $blockId ) {
|
||||
$this->blockId = (int)$blockId;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getValue() {
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function newFromRow( \stdClass $row ) {
|
||||
return new static( $row->ir_ipb_id, $row->ir_value );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toRow() {
|
||||
return [
|
||||
'ir_ipb_id' => $this->getBlockId(),
|
||||
'ir_type' => $this->getTypeId(),
|
||||
'ir_value' => $this->getValue(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function equals( Restriction $other ) {
|
||||
return $this->getHash() === $other->getHash();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getHash() {
|
||||
return $this->getType() . '-' . $this->getValue();
|
||||
}
|
||||
}
|
||||
99
includes/block/Restriction/PageRestriction.php
Normal file
99
includes/block/Restriction/PageRestriction.php
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
<?php
|
||||
/**
|
||||
* A Block restriction object of type 'Page'.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* @file
|
||||
*/
|
||||
|
||||
namespace MediaWiki\Block\Restriction;
|
||||
|
||||
class PageRestriction extends AbstractRestriction {
|
||||
|
||||
const TYPE = 'page';
|
||||
const TYPE_ID = 1;
|
||||
|
||||
/**
|
||||
* @var \Title
|
||||
*/
|
||||
protected $title;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function matches( \Title $title ) {
|
||||
return $title->equals( $this->getTitle() );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getType() {
|
||||
return self::TYPE;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTypeId() {
|
||||
return self::TYPE_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the title.
|
||||
*
|
||||
* @param \Title $title
|
||||
* @return self
|
||||
*/
|
||||
public function setTitle( \Title $title ) {
|
||||
$this->title = $title;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Title.
|
||||
*
|
||||
* @return \Title|null
|
||||
*/
|
||||
public function getTitle() {
|
||||
if ( !$this->title ) {
|
||||
$this->title = \Title::newFromID( $this->value );
|
||||
}
|
||||
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function newFromRow( \stdClass $row ) {
|
||||
$restriction = parent::newFromRow( $row );
|
||||
|
||||
// If the page_namespace and the page_title were provided, add the title to
|
||||
// the restriction.
|
||||
if ( isset( $row->page_namespace ) && isset( $row->page_title ) ) {
|
||||
// Clone the row so it is not mutated.
|
||||
$row = clone $row;
|
||||
$row->page_id = $row->ir_value;
|
||||
$title = \Title::newFromRow( $row );
|
||||
$restriction->setTitle( $title );
|
||||
}
|
||||
|
||||
return $restriction;
|
||||
}
|
||||
}
|
||||
100
includes/block/Restriction/Restriction.php
Normal file
100
includes/block/Restriction/Restriction.php
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
<?php
|
||||
/**
|
||||
* Block restriction interface.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* @file
|
||||
*/
|
||||
|
||||
namespace MediaWiki\Block\Restriction;
|
||||
|
||||
interface Restriction {
|
||||
|
||||
/**
|
||||
* Gets the id of the block.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getBlockId();
|
||||
|
||||
/**
|
||||
* Sets the id of the block.
|
||||
*
|
||||
* @param int $blockId
|
||||
* @return self
|
||||
*/
|
||||
public function setBlockId( $blockId );
|
||||
|
||||
/**
|
||||
* Gets the value of the restriction.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getValue();
|
||||
|
||||
/**
|
||||
* Gets the type of restriction
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getType();
|
||||
|
||||
/**
|
||||
* Gets the id of the type of restriction. This id is used in the database.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTypeId();
|
||||
|
||||
/**
|
||||
* Creates a new Restriction from a database row.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public static function newFromRow( \stdClass $row );
|
||||
|
||||
/**
|
||||
* Convert a restriction object into a row array for insertion.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toRow();
|
||||
|
||||
/**
|
||||
* Determine if a restriction matches a given title.
|
||||
*
|
||||
* @param \Title $title
|
||||
* @return bool
|
||||
*/
|
||||
public function matches( \Title $title );
|
||||
|
||||
/**
|
||||
* Determine if a restriction equals another restriction.
|
||||
*
|
||||
* @param Restriction $other
|
||||
* @return bool
|
||||
*/
|
||||
public function equals( Restriction $other );
|
||||
|
||||
/**
|
||||
* Create a unique hash of the block restriction based on the type and value.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getHash();
|
||||
|
||||
}
|
||||
|
|
@ -783,6 +783,7 @@ class SpecialBlock extends FormSpecialPage {
|
|||
$currentBlock->prevents( 'sendemail', $block->prevents( 'sendemail' ) );
|
||||
$currentBlock->prevents( 'editownusertalk', $block->prevents( 'editownusertalk' ) );
|
||||
$currentBlock->mReason = $block->mReason;
|
||||
$currentBlock->isSitewide( $block->isSitewide() );
|
||||
|
||||
$status = $currentBlock->update();
|
||||
|
||||
|
|
|
|||
|
|
@ -93,6 +93,9 @@ $wgAutoloadClasses += [
|
|||
'MediaWiki\\Auth\\AuthenticationRequestTestCase' =>
|
||||
"$testDir/phpunit/includes/auth/AuthenticationRequestTestCase.php",
|
||||
|
||||
# tests/phpunit/includes/block
|
||||
'MediaWiki\\Tests\\Block\\Restriction\\RestrictionTestCase' => "$testDir/phpunit/includes/block/Restriction/RestrictionTestCase.php",
|
||||
|
||||
# tests/phpunit/includes/changes
|
||||
'TestRecentChangesHelper' => "$testDir/phpunit/includes/changes/TestRecentChangesHelper.php",
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
use MediaWiki\Block\Restriction\PageRestriction;
|
||||
|
||||
/**
|
||||
* @group Database
|
||||
* @group Blocking
|
||||
|
|
@ -460,4 +462,152 @@ class BlockTest extends MediaWikiLangTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Block::newFromRow
|
||||
*/
|
||||
public function testNewFromRow() {
|
||||
$badActor = $this->getTestUser()->getUser();
|
||||
$sysop = $this->getTestSysop()->getUser();
|
||||
|
||||
$block = new Block( [
|
||||
'address' => $badActor->getName(),
|
||||
'user' => $badActor->getId(),
|
||||
'by' => $sysop->getId(),
|
||||
'expiry' => 'infinity',
|
||||
] );
|
||||
$block->insert();
|
||||
|
||||
$blockQuery = Block::getQueryInfo();
|
||||
$row = $this->db->select(
|
||||
$blockQuery['tables'],
|
||||
$blockQuery['fields'],
|
||||
[
|
||||
'ipb_id' => $block->getId(),
|
||||
],
|
||||
__METHOD__,
|
||||
[],
|
||||
$blockQuery['joins']
|
||||
)->fetchObject();
|
||||
|
||||
$block = Block::newFromRow( $row );
|
||||
$this->assertInstanceOf( Block::class, $block );
|
||||
$this->assertEquals( $block->getBy(), $sysop->getId() );
|
||||
$this->assertEquals( $block->getTarget()->getName(), $badActor->getName() );
|
||||
$block->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Block::equals
|
||||
*/
|
||||
public function testEquals() {
|
||||
$block = new Block();
|
||||
|
||||
$this->assertTrue( $block->equals( $block ) );
|
||||
|
||||
$partial = new Block( [
|
||||
'sitewide' => false,
|
||||
] );
|
||||
$this->assertFalse( $block->equals( $partial ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Block::isSitewide
|
||||
*/
|
||||
public function testIsSitewide() {
|
||||
$block = new Block();
|
||||
$this->assertTrue( $block->isSitewide() );
|
||||
|
||||
$block = new Block( [
|
||||
'sitewide' => true,
|
||||
] );
|
||||
$this->assertTrue( $block->isSitewide() );
|
||||
|
||||
$block = new Block( [
|
||||
'sitewide' => false,
|
||||
] );
|
||||
$this->assertFalse( $block->isSitewide() );
|
||||
|
||||
$block = new Block( [
|
||||
'sitewide' => false,
|
||||
] );
|
||||
$block->isSitewide( true );
|
||||
$this->assertTrue( $block->isSitewide() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Block::getRestrictions
|
||||
* @covers Block::setRestrictions
|
||||
*/
|
||||
public function testRestrictions() {
|
||||
$block = new Block();
|
||||
$restrictions = [
|
||||
new PageRestriction( 0, 1 )
|
||||
];
|
||||
$block->setRestrictions( $restrictions );
|
||||
|
||||
$this->assertSame( $restrictions, $block->getRestrictions() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Block::getRestrictions
|
||||
* @covers Block::insert
|
||||
*/
|
||||
public function testRestrictionsFromDatabase() {
|
||||
$badActor = $this->getTestUser()->getUser();
|
||||
$sysop = $this->getTestSysop()->getUser();
|
||||
|
||||
$block = new Block( [
|
||||
'address' => $badActor->getName(),
|
||||
'user' => $badActor->getId(),
|
||||
'by' => $sysop->getId(),
|
||||
'expiry' => 'infinity',
|
||||
] );
|
||||
$page = $this->getExistingTestPage( 'Foo' );
|
||||
$restriction = new PageRestriction( 0, $page->getId() );
|
||||
$block->setRestrictions( [ $restriction ] );
|
||||
$block->insert();
|
||||
|
||||
// Refresh the block from the database.
|
||||
$block = Block::newFromID( $block->getId() );
|
||||
$restrictions = $block->getRestrictions();
|
||||
$this->assertCount( 1, $restrictions );
|
||||
$this->assertTrue( $restriction->equals( $restrictions[0] ) );
|
||||
$block->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Block::insert
|
||||
*/
|
||||
public function testInsertExistingBlock() {
|
||||
$badActor = $this->getTestUser()->getUser();
|
||||
$sysop = $this->getTestSysop()->getUser();
|
||||
|
||||
$block = new Block( [
|
||||
'address' => $badActor->getName(),
|
||||
'user' => $badActor->getId(),
|
||||
'by' => $sysop->getId(),
|
||||
'expiry' => 'infinity',
|
||||
] );
|
||||
$page = $this->getExistingTestPage( 'Foo' );
|
||||
$restriction = new PageRestriction( 0, $page->getId() );
|
||||
$block->setRestrictions( [ $restriction ] );
|
||||
$block->insert();
|
||||
|
||||
// Insert the block again, which should result in a failur
|
||||
$result = $block->insert();
|
||||
|
||||
$this->assertFalse( $result );
|
||||
|
||||
// Ensure that there are no restrictions where the blockId is 0.
|
||||
$count = $this->db->selectRowCount(
|
||||
'ipblocks_restrictions',
|
||||
'*',
|
||||
[ 'ir_ipb_id' => 0 ],
|
||||
__METHOD__
|
||||
);
|
||||
$this->assertSame( 0, $count );
|
||||
|
||||
$block->delete();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
556
tests/phpunit/includes/block/BlockRestrictionTest.php
Normal file
556
tests/phpunit/includes/block/BlockRestrictionTest.php
Normal file
|
|
@ -0,0 +1,556 @@
|
|||
<?php
|
||||
|
||||
namespace MediaWiki\Tests\Block;
|
||||
|
||||
use MediaWiki\Block\BlockRestriction;
|
||||
use MediaWiki\Block\Restriction\PageRestriction;
|
||||
use MediaWiki\Block\Restriction\Restriction;
|
||||
|
||||
/**
|
||||
* @group Database
|
||||
* @group Blocking
|
||||
* @coversDefaultClass \MediaWiki\Block\BlockRestriction
|
||||
*/
|
||||
class BlockRestrictionTest extends \MediaWikiLangTestCase {
|
||||
|
||||
public function tearDown() {
|
||||
parent::tearDown();
|
||||
$this->resetTables();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::loadByBlockId
|
||||
* @covers ::resultToRestrictions
|
||||
* @covers ::rowToRestriction
|
||||
*/
|
||||
public function testLoadMultipleRestrictions() {
|
||||
$block = $this->insertBlock();
|
||||
|
||||
$pageFoo = $this->getExistingTestPage( 'Foo' );
|
||||
$pageBar = $this->getExistingTestPage( 'Bar' );
|
||||
|
||||
BlockRestriction::insert( [
|
||||
new PageRestriction( $block->getId(), $pageFoo->getId() ),
|
||||
new PageRestriction( $block->getId(), $pageBar->getId() ),
|
||||
] );
|
||||
|
||||
$restrictions = BlockRestriction::loadByBlockId( $block->getId() );
|
||||
|
||||
$this->assertCount( 2, $restrictions );
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::loadByBlockId
|
||||
* @covers ::resultToRestrictions
|
||||
* @covers ::rowToRestriction
|
||||
*/
|
||||
public function testWithNoRestrictions() {
|
||||
$block = $this->insertBlock();
|
||||
$restrictions = BlockRestriction::loadByBlockId( $block->getId() );
|
||||
$this->assertEmpty( $restrictions );
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::loadByBlockId
|
||||
* @covers ::resultToRestrictions
|
||||
* @covers ::rowToRestriction
|
||||
*/
|
||||
public function testWithEmptyParam() {
|
||||
$restrictions = BlockRestriction::loadByBlockId( [] );
|
||||
|
||||
$this->assertEmpty( $restrictions );
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::loadByBlockId
|
||||
* @covers ::resultToRestrictions
|
||||
* @covers ::rowToRestriction
|
||||
*/
|
||||
public function testIgnoreNotSupportedTypes() {
|
||||
$block = $this->insertBlock();
|
||||
|
||||
$pageFoo = $this->getExistingTestPage( 'Foo' );
|
||||
$pageBar = $this->getExistingTestPage( 'Bar' );
|
||||
|
||||
// valid type
|
||||
$this->insertRestriction( $block->getId(), PageRestriction::TYPE_ID, $pageFoo->getId() );
|
||||
|
||||
// invalid type
|
||||
$this->insertRestriction( $block->getId(), 9, $pageBar->getId() );
|
||||
|
||||
$restrictions = BlockRestriction::loadByBlockId( $block->getId() );
|
||||
$this->assertCount( 1, $restrictions );
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::loadByBlockId
|
||||
* @covers ::resultToRestrictions
|
||||
* @covers ::rowToRestriction
|
||||
*/
|
||||
public function testMappingRestrictionObject() {
|
||||
$block = $this->insertBlock();
|
||||
$title = 'Lady Macbeth';
|
||||
$page = $this->getExistingTestPage( $title );
|
||||
|
||||
BlockRestriction::insert( [
|
||||
new PageRestriction( $block->getId(), $page->getId() ),
|
||||
] );
|
||||
|
||||
$restrictions = BlockRestriction::loadByBlockId( $block->getId() );
|
||||
|
||||
list( $pageRestriction ) = $restrictions;
|
||||
$this->assertInstanceOf( PageRestriction::class, $pageRestriction );
|
||||
$this->assertEquals( $block->getId(), $pageRestriction->getBlockId() );
|
||||
$this->assertEquals( $page->getId(), $pageRestriction->getValue() );
|
||||
$this->assertEquals( $pageRestriction->getType(), PageRestriction::TYPE );
|
||||
$this->assertEquals( $pageRestriction->getTitle()->getText(), $title );
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::insert
|
||||
*/
|
||||
public function testInsert() {
|
||||
$block = $this->insertBlock();
|
||||
|
||||
$pageFoo = $this->getExistingTestPage( 'Foo' );
|
||||
$pageBar = $this->getExistingTestPage( 'Bar' );
|
||||
|
||||
$restrictions = [
|
||||
new \stdClass(),
|
||||
new PageRestriction( $block->getId(), $pageFoo->getId() ),
|
||||
new PageRestriction( $block->getId(), $pageBar->getId() ),
|
||||
];
|
||||
|
||||
$result = BlockRestriction::insert( $restrictions );
|
||||
$this->assertTrue( $result );
|
||||
|
||||
$restrictions = [
|
||||
new \stdClass(),
|
||||
];
|
||||
|
||||
$result = BlockRestriction::insert( $restrictions );
|
||||
$this->assertFalse( $result );
|
||||
|
||||
$result = BlockRestriction::insert( [] );
|
||||
$this->assertFalse( $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::insert
|
||||
*/
|
||||
public function testInsertTypes() {
|
||||
$block = $this->insertBlock();
|
||||
|
||||
$pageFoo = $this->getExistingTestPage( 'Foo' );
|
||||
$pageBar = $this->getExistingTestPage( 'Bar' );
|
||||
|
||||
$namespace = $this->createMock( Restriction::class );
|
||||
$namespace->method( 'toRow' )
|
||||
->willReturn( [
|
||||
'ir_ipb_id' => $block->getId(),
|
||||
'ir_type' => 2,
|
||||
'ir_value' => 0,
|
||||
] );
|
||||
|
||||
$invalid = $this->createMock( Restriction::class );
|
||||
$invalid->method( 'toRow' )
|
||||
->willReturn( [
|
||||
'ir_ipb_id' => $block->getId(),
|
||||
'ir_type' => 9,
|
||||
'ir_value' => 42,
|
||||
] );
|
||||
|
||||
$restrictions = [
|
||||
new \stdClass(),
|
||||
new PageRestriction( $block->getId(), $pageFoo->getId() ),
|
||||
new PageRestriction( $block->getId(), $pageBar->getId() ),
|
||||
$namespace,
|
||||
$invalid,
|
||||
];
|
||||
|
||||
$result = BlockRestriction::insert( $restrictions );
|
||||
$this->assertTrue( $result );
|
||||
|
||||
$restrictions = BlockRestriction::loadByBlockId( $block->getId() );
|
||||
$this->assertCount( 2, $restrictions );
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::update
|
||||
* @covers ::restrictionsByBlockId
|
||||
* @covers ::restrictionsToRemove
|
||||
*/
|
||||
public function testUpdateInsert() {
|
||||
$block = $this->insertBlock();
|
||||
$pageFoo = $this->getExistingTestPage( 'Foo' );
|
||||
$pageBar = $this->getExistingTestPage( 'Bar' );
|
||||
BlockRestriction::insert( [
|
||||
new PageRestriction( $block->getId(), $pageFoo->getId() ),
|
||||
] );
|
||||
|
||||
BlockRestriction::update( [
|
||||
new \stdClass(),
|
||||
new PageRestriction( $block->getId(), $pageBar->getId() ),
|
||||
] );
|
||||
|
||||
$db = wfGetDb( DB_REPLICA );
|
||||
$result = $db->select(
|
||||
[ 'ipblocks_restrictions' ],
|
||||
[ '*' ],
|
||||
[ 'ir_ipb_id' => $block->getId() ]
|
||||
);
|
||||
|
||||
$this->assertEquals( 1, $result->numRows() );
|
||||
$row = $result->fetchObject();
|
||||
$this->assertEquals( $block->getId(), $row->ir_ipb_id );
|
||||
$this->assertEquals( $pageBar->getId(), $row->ir_value );
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::update
|
||||
* @covers ::restrictionsByBlockId
|
||||
* @covers ::restrictionsToRemove
|
||||
*/
|
||||
public function testUpdateChange() {
|
||||
$block = $this->insertBlock();
|
||||
$page = $this->getExistingTestPage( 'Foo' );
|
||||
|
||||
BlockRestriction::update( [
|
||||
new PageRestriction( $block->getId(), $page->getId() ),
|
||||
] );
|
||||
|
||||
$db = wfGetDb( DB_REPLICA );
|
||||
$result = $db->select(
|
||||
[ 'ipblocks_restrictions' ],
|
||||
[ '*' ],
|
||||
[ 'ir_ipb_id' => $block->getId() ]
|
||||
);
|
||||
|
||||
$this->assertEquals( 1, $result->numRows() );
|
||||
$row = $result->fetchObject();
|
||||
$this->assertEquals( $block->getId(), $row->ir_ipb_id );
|
||||
$this->assertEquals( $page->getId(), $row->ir_value );
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::update
|
||||
* @covers ::restrictionsByBlockId
|
||||
* @covers ::restrictionsToRemove
|
||||
*/
|
||||
public function testUpdateNoRestrictions() {
|
||||
$block = $this->insertBlock();
|
||||
|
||||
BlockRestriction::update( [] );
|
||||
|
||||
$db = wfGetDb( DB_REPLICA );
|
||||
$result = $db->select(
|
||||
[ 'ipblocks_restrictions' ],
|
||||
[ '*' ],
|
||||
[ 'ir_ipb_id' => $block->getId() ]
|
||||
);
|
||||
|
||||
$this->assertEquals( 0, $result->numRows() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::update
|
||||
* @covers ::restrictionsByBlockId
|
||||
* @covers ::restrictionsToRemove
|
||||
*/
|
||||
public function testUpdateSame() {
|
||||
$block = $this->insertBlock();
|
||||
$page = $this->getExistingTestPage( 'Foo' );
|
||||
BlockRestriction::insert( [
|
||||
new PageRestriction( $block->getId(), $page->getId() ),
|
||||
] );
|
||||
|
||||
BlockRestriction::update( [
|
||||
new PageRestriction( $block->getId(), $page->getId() ),
|
||||
] );
|
||||
|
||||
$db = wfGetDb( DB_REPLICA );
|
||||
$result = $db->select(
|
||||
[ 'ipblocks_restrictions' ],
|
||||
[ '*' ],
|
||||
[ 'ir_ipb_id' => $block->getId() ]
|
||||
);
|
||||
|
||||
$this->assertEquals( 1, $result->numRows() );
|
||||
$row = $result->fetchObject();
|
||||
$this->assertEquals( $block->getId(), $row->ir_ipb_id );
|
||||
$this->assertEquals( $page->getId(), $row->ir_value );
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::updateByParentBlockId
|
||||
*/
|
||||
public function testDeleteAllUpdateByParentBlockId() {
|
||||
// Create a block and an autoblock (a child block)
|
||||
$block = $this->insertBlock();
|
||||
$pageFoo = $this->getExistingTestPage( 'Foo' );
|
||||
$pageBar = $this->getExistingTestPage( 'Bar' );
|
||||
BlockRestriction::insert( [
|
||||
new PageRestriction( $block->getId(), $pageFoo->getId() ),
|
||||
] );
|
||||
$autoblockId = $block->doAutoblock( '127.0.0.1' );
|
||||
|
||||
// Ensure that the restrictions on the block have not changed.
|
||||
$restrictions = BlockRestriction::loadByBlockId( $block->getId() );
|
||||
$this->assertCount( 1, $restrictions );
|
||||
$this->assertEquals( $pageFoo->getId(), $restrictions[0]->getValue() );
|
||||
|
||||
// Ensure that the restrictions on the autoblock are the same as the block.
|
||||
$restrictions = BlockRestriction::loadByBlockId( $autoblockId );
|
||||
$this->assertCount( 1, $restrictions );
|
||||
$this->assertEquals( $pageFoo->getId(), $restrictions[0]->getValue() );
|
||||
|
||||
// Update the restrictions on the autoblock (but leave the block unchanged)
|
||||
BlockRestriction::updateByParentBlockId( $block->getId(), [
|
||||
new PageRestriction( $block->getId(), $pageBar->getId() ),
|
||||
] );
|
||||
|
||||
// Ensure that the restrictions on the block have not changed.
|
||||
$restrictions = BlockRestriction::loadByBlockId( $block->getId() );
|
||||
$this->assertCount( 1, $restrictions );
|
||||
$this->assertEquals( $pageFoo->getId(), $restrictions[0]->getValue() );
|
||||
|
||||
// Ensure that the restrictions on the autoblock have been updated.
|
||||
$restrictions = BlockRestriction::loadByBlockId( $autoblockId );
|
||||
$this->assertCount( 1, $restrictions );
|
||||
$this->assertEquals( $pageBar->getId(), $restrictions[0]->getValue() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::updateByParentBlockId
|
||||
*/
|
||||
public function testUpdateByParentBlockId() {
|
||||
// Create a block and an autoblock (a child block)
|
||||
$block = $this->insertBlock();
|
||||
$page = $this->getExistingTestPage( 'Foo' );
|
||||
BlockRestriction::insert( [
|
||||
new PageRestriction( $block->getId(), $page->getId() ),
|
||||
] );
|
||||
$autoblockId = $block->doAutoblock( '127.0.0.1' );
|
||||
|
||||
// Ensure that the restrictions on the block have not changed.
|
||||
$restrictions = BlockRestriction::loadByBlockId( $block->getId() );
|
||||
$this->assertCount( 1, $restrictions );
|
||||
|
||||
// Ensure that the restrictions on the autoblock have not changed.
|
||||
$restrictions = BlockRestriction::loadByBlockId( $autoblockId );
|
||||
$this->assertCount( 1, $restrictions );
|
||||
|
||||
// Remove the restrictions on the autoblock (but leave the block unchanged)
|
||||
BlockRestriction::updateByParentBlockId( $block->getId(), [] );
|
||||
|
||||
// Ensure that the restrictions on the block have not changed.
|
||||
$restrictions = BlockRestriction::loadByBlockId( $block->getId() );
|
||||
$this->assertCount( 1, $restrictions );
|
||||
|
||||
// Ensure that the restrictions on the autoblock have been updated.
|
||||
$restrictions = BlockRestriction::loadByBlockId( $autoblockId );
|
||||
$this->assertCount( 0, $restrictions );
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::updateByParentBlockId
|
||||
*/
|
||||
public function testNoAutoblocksUpdateByParentBlockId() {
|
||||
// Create a block with no autoblock.
|
||||
$block = $this->insertBlock();
|
||||
$page = $this->getExistingTestPage( 'Foo' );
|
||||
BlockRestriction::insert( [
|
||||
new PageRestriction( $block->getId(), $page->getId() ),
|
||||
] );
|
||||
|
||||
// Ensure that the restrictions on the block have not changed.
|
||||
$restrictions = BlockRestriction::loadByBlockId( $block->getId() );
|
||||
$this->assertCount( 1, $restrictions );
|
||||
|
||||
// Update the restrictions on any autoblocks (there are none).
|
||||
BlockRestriction::updateByParentBlockId( $block->getId(), $restrictions );
|
||||
|
||||
// Ensure that the restrictions on the block have not changed.
|
||||
$restrictions = BlockRestriction::loadByBlockId( $block->getId() );
|
||||
$this->assertCount( 1, $restrictions );
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::delete
|
||||
*/
|
||||
public function testDelete() {
|
||||
$block = $this->insertBlock();
|
||||
$page = $this->getExistingTestPage( 'Foo' );
|
||||
BlockRestriction::insert( [
|
||||
new PageRestriction( $block->getId(), $page->getId() ),
|
||||
] );
|
||||
|
||||
$restrictions = BlockRestriction::loadByBlockId( $block->getId() );
|
||||
$this->assertCount( 1, $restrictions );
|
||||
|
||||
$result = BlockRestriction::delete( array_merge( $restrictions, [ new \stdClass() ] ) );
|
||||
$this->assertTrue( $result );
|
||||
|
||||
$restrictions = BlockRestriction::loadByBlockId( $block->getId() );
|
||||
$this->assertCount( 0, $restrictions );
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::deleteByBlockId
|
||||
*/
|
||||
public function testDeleteByBlockId() {
|
||||
$block = $this->insertBlock();
|
||||
$page = $this->getExistingTestPage( 'Foo' );
|
||||
BlockRestriction::insert( [
|
||||
new PageRestriction( $block->getId(), $page->getId() ),
|
||||
] );
|
||||
|
||||
$restrictions = BlockRestriction::loadByBlockId( $block->getId() );
|
||||
$this->assertCount( 1, $restrictions );
|
||||
|
||||
$result = BlockRestriction::deleteByBlockId( $block->getId() );
|
||||
$this->assertNotFalse( $result );
|
||||
|
||||
$restrictions = BlockRestriction::loadByBlockId( $block->getId() );
|
||||
$this->assertCount( 0, $restrictions );
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::deleteByParentBlockId
|
||||
*/
|
||||
public function testDeleteByParentBlockId() {
|
||||
// Create a block with no autoblock.
|
||||
$block = $this->insertBlock();
|
||||
$page = $this->getExistingTestPage( 'Foo' );
|
||||
BlockRestriction::insert( [
|
||||
new PageRestriction( $block->getId(), $page->getId() ),
|
||||
] );
|
||||
$autoblockId = $block->doAutoblock( '127.0.0.1' );
|
||||
|
||||
// Ensure that the restrictions on the block have not changed.
|
||||
$restrictions = BlockRestriction::loadByBlockId( $block->getId() );
|
||||
$this->assertCount( 1, $restrictions );
|
||||
|
||||
// Ensure that the restrictions on the autoblock are the same as the block.
|
||||
$restrictions = BlockRestriction::loadByBlockId( $autoblockId );
|
||||
$this->assertCount( 1, $restrictions );
|
||||
|
||||
// Remove all of the restrictions on the autoblock (but leave the block unchanged).
|
||||
$result = BlockRestriction::deleteByParentBlockId( $block->getId() );
|
||||
// NOTE: commented out until https://gerrit.wikimedia.org/r/c/mediawiki/core/+/469324 is merged
|
||||
//$this->assertTrue( $result );
|
||||
|
||||
// Ensure that the restrictions on the block have not changed.
|
||||
$restrictions = BlockRestriction::loadByBlockId( $block->getId() );
|
||||
$this->assertCount( 1, $restrictions );
|
||||
|
||||
// Ensure that the restrictions on the autoblock have been removed.
|
||||
$restrictions = BlockRestriction::loadByBlockId( $autoblockId );
|
||||
$this->assertCount( 0, $restrictions );
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::equals
|
||||
* @dataProvider equalsDataProvider
|
||||
*
|
||||
* @param array $a
|
||||
* @param array $b
|
||||
* @param bool $expected
|
||||
*/
|
||||
public function testEquals( array $a, array $b, $expected ) {
|
||||
$this->assertSame( $expected, BlockRestriction::equals( $a, $b ) );
|
||||
}
|
||||
|
||||
public function equalsDataProvider() {
|
||||
return [
|
||||
[
|
||||
[
|
||||
new \stdClass(),
|
||||
new PageRestriction( 1, 1 ),
|
||||
],
|
||||
[
|
||||
new \stdClass(),
|
||||
new PageRestriction( 1, 2 )
|
||||
],
|
||||
false,
|
||||
],
|
||||
[
|
||||
[
|
||||
new PageRestriction( 1, 1 ),
|
||||
],
|
||||
[
|
||||
new PageRestriction( 1, 1 ),
|
||||
new PageRestriction( 1, 2 )
|
||||
],
|
||||
false,
|
||||
],
|
||||
[
|
||||
[],
|
||||
[],
|
||||
true,
|
||||
],
|
||||
[
|
||||
[
|
||||
new PageRestriction( 1, 1 ),
|
||||
new PageRestriction( 1, 2 ),
|
||||
new PageRestriction( 2, 3 ),
|
||||
],
|
||||
[
|
||||
new PageRestriction( 2, 3 ),
|
||||
new PageRestriction( 1, 2 ),
|
||||
new PageRestriction( 1, 1 ),
|
||||
],
|
||||
true
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::setBlockId
|
||||
*/
|
||||
public function testSetBlockId() {
|
||||
$restrictions = [
|
||||
new \stdClass(),
|
||||
new PageRestriction( 1, 1 ),
|
||||
new PageRestriction( 1, 2 ),
|
||||
];
|
||||
|
||||
$result = BlockRestriction::setBlockId( 2, $restrictions );
|
||||
|
||||
$this->assertSame( 1, $restrictions[1]->getBlockId() );
|
||||
$this->assertSame( 1, $restrictions[2]->getBlockId() );
|
||||
$this->assertSame( 2, $result[0]->getBlockId() );
|
||||
$this->assertSame( 2, $result[1]->getBlockId() );
|
||||
}
|
||||
|
||||
protected function insertBlock() {
|
||||
$badActor = $this->getTestUser()->getUser();
|
||||
$sysop = $this->getTestSysop()->getUser();
|
||||
|
||||
$block = new \Block( [
|
||||
'address' => $badActor->getName(),
|
||||
'user' => $badActor->getId(),
|
||||
'by' => $sysop->getId(),
|
||||
'expiry' => 'infinity',
|
||||
'sitewide' => 0,
|
||||
'enableAutoblock' => true,
|
||||
] );
|
||||
|
||||
$block->insert();
|
||||
|
||||
return $block;
|
||||
}
|
||||
|
||||
protected function insertRestriction( $blockId, $type, $value ) {
|
||||
$this->db->insert( 'ipblocks_restrictions', [
|
||||
'ir_ipb_id' => $blockId,
|
||||
'ir_type' => $type,
|
||||
'ir_value' => $value,
|
||||
] );
|
||||
}
|
||||
|
||||
protected function resetTables() {
|
||||
$this->db->delete( 'ipblocks', '*', __METHOD__ );
|
||||
$this->db->delete( 'ipblocks_restrictions', '*', __METHOD__ );
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
|
||||
namespace MediaWiki\Tests\Block\Restriction;
|
||||
|
||||
use MediaWiki\Block\Restriction\PageRestriction;
|
||||
|
||||
/**
|
||||
* @group Database
|
||||
* @group Blocking
|
||||
* @covers \MediaWiki\Block\Restriction\AbstractRestriction
|
||||
* @covers \MediaWiki\Block\Restriction\PageRestriction
|
||||
*/
|
||||
class PageRestrictionTest extends RestrictionTestCase {
|
||||
|
||||
public function testMatches() {
|
||||
$class = $this->getClass();
|
||||
$page = $this->getExistingTestPage( 'Saturn' );
|
||||
$restriction = new $class( 1, $page->getId() );
|
||||
$this->assertTrue( $restriction->matches( $page->getTitle() ) );
|
||||
|
||||
$page = $this->getExistingTestPage( 'Mars' );
|
||||
$this->assertFalse( $restriction->matches( $page->getTitle() ) );
|
||||
}
|
||||
|
||||
public function testGetType() {
|
||||
$class = $this->getClass();
|
||||
$restriction = new $class( 1, 2 );
|
||||
$this->assertEquals( 'page', $restriction->getType() );
|
||||
}
|
||||
|
||||
public function testGetTitle() {
|
||||
$class = $this->getClass();
|
||||
$restriction = new $class( 1, 2 );
|
||||
$title = \Title::newFromText( 'Pluto' );
|
||||
$title->mArticleID = 2;
|
||||
$restriction->setTitle( $title );
|
||||
$this->assertSame( $title, $restriction->getTitle() );
|
||||
|
||||
$restriction = new $class( 1, 1 );
|
||||
$title = \Title::newFromId( 1 );
|
||||
$this->assertEquals( $title->getArticleId(), $restriction->getTitle()->getArticleId() );
|
||||
}
|
||||
|
||||
public function testNewFromRow() {
|
||||
$class = $this->getClass();
|
||||
$restriction = $class::newFromRow( (object)[
|
||||
'ir_ipb_id' => 1,
|
||||
'ir_value' => 2,
|
||||
'page_namespace' => 0,
|
||||
'page_title' => 'Saturn',
|
||||
] );
|
||||
|
||||
$this->assertSame( 1, $restriction->getBlockId() );
|
||||
$this->assertSame( 2, $restriction->getValue() );
|
||||
$this->assertSame( 'Saturn', $restriction->getTitle()->getText() );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getClass() {
|
||||
return PageRestriction::class;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
|
||||
namespace MediaWiki\Tests\Block\Restriction;
|
||||
|
||||
/**
|
||||
* @group Blocking
|
||||
*/
|
||||
abstract class RestrictionTestCase extends \MediaWikiTestCase {
|
||||
public function testConstruct() {
|
||||
$class = $this->getClass();
|
||||
$restriction = new $class( 1, 2 );
|
||||
|
||||
$this->assertSame( $restriction->getBlockId(), 1 );
|
||||
$this->assertSame( $restriction->getValue(), 2 );
|
||||
}
|
||||
|
||||
public function testSetBlockId() {
|
||||
$class = $this->getClass();
|
||||
$restriction = new $class( 1, 2 );
|
||||
|
||||
$restriction->setBlockId( 10 );
|
||||
$this->assertSame( $restriction->getBlockId(), 10 );
|
||||
}
|
||||
|
||||
public function testEquals() {
|
||||
$class = $this->getClass();
|
||||
|
||||
// Test two restrictions with the same data.
|
||||
$restriction = new $class( 1, 2 );
|
||||
$second = new $class( 1, 2 );
|
||||
$this->assertTrue( $restriction->equals( $second ) );
|
||||
|
||||
// Test two restrictions that implement different classes.
|
||||
$second = $this->createMock( $this->getClass() );
|
||||
$this->assertFalse( $restriction->equals( $second ) );
|
||||
|
||||
// Not the same block id.
|
||||
$second = new $class( 2, 2 );
|
||||
$this->assertTrue( $restriction->equals( $second ) );
|
||||
|
||||
// Not the same value.
|
||||
$second = new $class( 1, 3 );
|
||||
$this->assertFalse( $restriction->equals( $second ) );
|
||||
}
|
||||
|
||||
public function testNewFromRow() {
|
||||
$class = $this->getClass();
|
||||
|
||||
$restriction = $class::newFromRow( (object)[
|
||||
'ir_ipb_id' => 1,
|
||||
'ir_value' => 2,
|
||||
] );
|
||||
|
||||
$this->assertSame( 1, $restriction->getBlockId() );
|
||||
$this->assertSame( 2, $restriction->getValue() );
|
||||
}
|
||||
|
||||
public function testToRow() {
|
||||
$class = $this->getClass();
|
||||
|
||||
$restriction = new $class( 1, 2 );
|
||||
$row = $restriction->toRow();
|
||||
|
||||
$this->assertSame( 1, $row['ir_ipb_id'] );
|
||||
$this->assertSame( 2, $row['ir_value'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the class name of the class that is being tested.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function getClass();
|
||||
}
|
||||
Loading…
Reference in a new issue