false,
'external' => false,
'ipallowed' => false,
'usemodwiki-ipallowed' => false,
'iprange' => false,
'iprangelimits' => [
'IPv4' => 0,
'IPv6' => 0,
],
'excludenamed' => false,
'excludetemp' => false,
]
);
parent::__construct( $params );
}
public function validate( $value, $alldata ) {
// If the value is null, reset it to an empty string which is what is expected by the parent.
$value ??= '';
// If the value is empty, there are no additional checks that can be performed.
if ( $value === '' ) {
return parent::validate( $value, $alldata );
}
// check if the input is a valid username
$user = MediaWikiServices::getInstance()->getUserFactory()->newFromName( $value );
if ( $user ) {
// check if the user exists, if requested
if ( $this->mParams['exists'] && !(
$user->isRegistered() &&
// Treat hidden users as unregistered if current user can't view them (T309894)
!( $user->isHidden() && !( $this->mParent && $this->mParent->getUser()->isAllowed( 'hideuser' ) ) )
) ) {
return $this->msg( 'htmlform-user-not-exists', $user->getName() );
}
// check if the user account type matches the account type filter
$excludeNamed = $this->mParams['excludenamed'] ?? null;
$excludeTemp = $this->mParams['excludetemp'] ?? null;
if ( ( $excludeTemp && $user->isTemp() ) || ( $excludeNamed && $user->isNamed() ) ) {
return $this->msg( 'htmlform-user-not-valid', $user->getName() );
}
} else {
// not a valid username
$valid = false;
// check if the input is a valid external user
if ( $this->mParams['external'] && ExternalUserNames::isExternal( $value ) ) {
$valid = true;
}
// check if the input is a valid IP address, optionally also checking for usemod wiki IPs
if ( $this->mParams['ipallowed'] ) {
$b = IPUtils::RE_IP_BYTE;
if ( IPUtils::isValid( $value ) ) {
$valid = true;
} elseif ( $this->mParams['usemodwiki-ipallowed'] && preg_match( "/^$b\.$b\.$b\.xxx$/", $value ) ) {
$valid = true;
}
}
// check if the input is a valid IP range
if ( $this->mParams['iprange'] ) {
$rangeError = $this->isValidIPRange( $value );
if ( $rangeError === true ) {
$valid = true;
} elseif ( $rangeError !== false ) {
return $rangeError;
}
}
if ( !$valid ) {
return $this->msg( 'htmlform-user-not-valid', $value );
}
}
return parent::validate( $value, $alldata );
}
protected function isValidIPRange( $value ) {
$cidrIPRanges = $this->mParams['iprangelimits'];
if ( !IPUtils::isValidRange( $value ) ) {
return false;
}
[ $ip, $range ] = explode( '/', $value, 2 );
if (
( IPUtils::isIPv4( $ip ) && $cidrIPRanges['IPv4'] == 32 ) ||
( IPUtils::isIPv6( $ip ) && $cidrIPRanges['IPv6'] == 128 )
) {
// Range block effectively disabled
return $this->msg( 'ip_range_toolow' );
}
if (
( IPUtils::isIPv4( $ip ) && $range > 32 ) ||
( IPUtils::isIPv6( $ip ) && $range > 128 )
) {
// Dodgy range
return $this->msg( 'ip_range_invalid' );
}
if ( IPUtils::isIPv4( $ip ) && $range < $cidrIPRanges['IPv4'] ) {
return $this->msg( 'ip_range_exceeded', $cidrIPRanges['IPv4'] );
}
if ( IPUtils::isIPv6( $ip ) && $range < $cidrIPRanges['IPv6'] ) {
return $this->msg( 'ip_range_exceeded', $cidrIPRanges['IPv6'] );
}
return true;
}
protected function getInputWidget( $params ) {
if ( isset( $this->mParams['excludenamed'] ) ) {
$params['excludenamed'] = $this->mParams['excludenamed'];
}
if ( isset( $this->mParams['excludetemp'] ) ) {
$params['excludetemp'] = $this->mParams['excludetemp'];
}
return new UserInputWidget( $params );
}
protected function shouldInfuseOOUI() {
return true;
}
protected function getOOUIModules() {
return [ 'mediawiki.widgets.UserInputWidget' ];
}
public function getInputHtml( $value ) {
// add the required module and css class for user suggestions in non-OOUI mode
$this->mParent->getOutput()->addModules( 'mediawiki.userSuggest' );
$this->mClass .= ' mw-autocomplete-user';
// return parent html
return parent::getInputHTML( $value );
}
}
/** @deprecated class alias since 1.42 */
class_alias( HTMLUserTextField::class, 'HTMLUserTextField' );