File: HTMLUserTextField.php

package info (click to toggle)
mediawiki 1%3A1.35.13-1%2Bdeb11u2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 274,932 kB
  • sloc: php: 677,563; javascript: 572,709; sql: 11,565; python: 4,447; xml: 3,145; sh: 892; perl: 788; ruby: 496; pascal: 365; makefile: 128
file content (133 lines) | stat: -rw-r--r-- 3,840 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
<?php

use MediaWiki\Widget\UserInputWidget;
use Wikimedia\IPUtils;

/**
 * Implements a text input field for user names.
 * Automatically auto-completes if using the OOUI display format.
 *
 * Optional parameters:
 * 'exists' - Whether to validate that the user already exists
 * 'ipallowed' - Whether an IP adress is interpreted as "valid"
 * 'iprange' - Whether an IP adress range is interpreted as "valid"
 * 'iprangelimits' - Specifies the valid IP ranges for IPv4 and IPv6 in an array.
 *  defaults to IPv4 => 16; IPv6 => 32.
 *
 * @stable to extend
 * @since 1.26
 */
class HTMLUserTextField extends HTMLTextField {
	/*
	 * @stable to call
	 */
	public function __construct( $params ) {
		$params = wfArrayPlus2d( $params, [
				'exists' => false,
				'ipallowed' => false,
				'iprange' => false,
				'iprangelimits' => [
					'IPv4' => '16',
					'IPv6' => '32',
				],
			]
		);

		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.
		if ( $value === null ) {
			$value = '';
		}

		// If the value is empty, there are no additional checks that can be performed.
		if ( $value === '' ) {
			return parent::validate( $value, $alldata );
		}

		// check, if a user exists with the given username
		$user = User::newFromName( $value, false );
		$rangeError = null;

		if ( !$user ) {
			return $this->msg( 'htmlform-user-not-valid', $value );
		} elseif (
			// check, if the user exists, if requested
			( $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' ) ) )
			) ) &&
			// check, if the username is a valid IP address, otherwise save the error message
			!( $this->mParams['ipallowed'] && IPUtils::isValid( $value ) ) &&
			// check, if the username is a valid IP range, otherwise save the error message
			!( $this->mParams['iprange'] && ( $rangeError = $this->isValidIPRange( $value ) ) === true )
		) {
			if ( is_string( $rangeError ) ) {
				return $rangeError;
			}
			return $this->msg( 'htmlform-user-not-exists', $user->getName() );
		}

		return parent::validate( $value, $alldata );
	}

	protected function isValidIPRange( $value ) {
		$cidrIPRanges = $this->mParams['iprangelimits'];

		if ( !IPUtils::isValidRange( $value ) ) {
			return false;
		}

		list( $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' )->parse();
		}

		if (
			( IPUtils::isIPv4( $ip ) && $range > 32 ) ||
			( IPUtils::isIPv6( $ip ) && $range > 128 )
		) {
			// Dodgy range
			return $this->msg( 'ip_range_invalid' )->parse();
		}

		if ( IPUtils::isIPv4( $ip ) && $range < $cidrIPRanges['IPv4'] ) {
			return $this->msg( 'ip_range_exceeded', $cidrIPRanges['IPv4'] )->parse();
		}

		if ( IPUtils::isIPv6( $ip ) && $range < $cidrIPRanges['IPv6'] ) {
			return $this->msg( 'ip_range_exceeded', $cidrIPRanges['IPv6'] )->parse();
		}

		return true;
	}

	protected function getInputWidget( $params ) {
		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 );
	}
}