HTMLUserTextField.php 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. <?php
  2. use MediaWiki\Widget\UserInputWidget;
  3. /**
  4. * Implements a text input field for user names.
  5. * Automatically auto-completes if using the OOUI display format.
  6. *
  7. * Optional parameters:
  8. * 'exists' - Whether to validate that the user already exists
  9. * 'ipallowed' - Whether an IP adress is interpreted as "valid"
  10. * 'iprange' - Whether an IP adress range is interpreted as "valid"
  11. * 'iprangelimits' - Specifies the valid IP ranges for IPv4 and IPv6 in an array.
  12. * defaults to IPv4 => 16; IPv6 => 32.
  13. *
  14. * @since 1.26
  15. */
  16. class HTMLUserTextField extends HTMLTextField {
  17. public function __construct( $params ) {
  18. $params = wfArrayPlus2d( $params, [
  19. 'exists' => false,
  20. 'ipallowed' => false,
  21. 'iprange' => false,
  22. 'iprangelimits' => [
  23. 'IPv4' => '16',
  24. 'IPv6' => '32',
  25. ],
  26. ]
  27. );
  28. parent::__construct( $params );
  29. }
  30. public function validate( $value, $alldata ) {
  31. // Default value (from getDefault()) is null, User::newFromName() expects a string
  32. if ( $value === null ) {
  33. $value = '';
  34. }
  35. // check, if a user exists with the given username
  36. $user = User::newFromName( $value, false );
  37. $rangeError = null;
  38. if ( !$user ) {
  39. return $this->msg( 'htmlform-user-not-valid', $value );
  40. } elseif (
  41. // check, if the user exists, if requested
  42. ( $this->mParams['exists'] && $user->getId() === 0 ) &&
  43. // check, if the username is a valid IP address, otherwise save the error message
  44. !( $this->mParams['ipallowed'] && IP::isValid( $value ) ) &&
  45. // check, if the username is a valid IP range, otherwise save the error message
  46. !( $this->mParams['iprange'] && ( $rangeError = $this->isValidIPRange( $value ) ) === true )
  47. ) {
  48. if ( is_string( $rangeError ) ) {
  49. return $rangeError;
  50. }
  51. return $this->msg( 'htmlform-user-not-exists', $user->getName() );
  52. }
  53. return parent::validate( $value, $alldata );
  54. }
  55. protected function isValidIPRange( $value ) {
  56. $cidrIPRanges = $this->mParams['iprangelimits'];
  57. if ( !IP::isValidRange( $value ) ) {
  58. return false;
  59. }
  60. list( $ip, $range ) = explode( '/', $value, 2 );
  61. if (
  62. ( IP::isIPv4( $ip ) && $cidrIPRanges['IPv4'] == 32 ) ||
  63. ( IP::isIPv6( $ip ) && $cidrIPRanges['IPv6'] == 128 )
  64. ) {
  65. // Range block effectively disabled
  66. return $this->msg( 'ip_range_toolow' )->parse();
  67. }
  68. if (
  69. ( IP::isIPv4( $ip ) && $range > 32 ) ||
  70. ( IP::isIPv6( $ip ) && $range > 128 )
  71. ) {
  72. // Dodgy range
  73. return $this->msg( 'ip_range_invalid' )->parse();
  74. }
  75. if ( IP::isIPv4( $ip ) && $range < $cidrIPRanges['IPv4'] ) {
  76. return $this->msg( 'ip_range_exceeded', $cidrIPRanges['IPv4'] )->parse();
  77. }
  78. if ( IP::isIPv6( $ip ) && $range < $cidrIPRanges['IPv6'] ) {
  79. return $this->msg( 'ip_range_exceeded', $cidrIPRanges['IPv6'] )->parse();
  80. }
  81. return true;
  82. }
  83. protected function getInputWidget( $params ) {
  84. return new UserInputWidget( $params );
  85. }
  86. protected function shouldInfuseOOUI() {
  87. return true;
  88. }
  89. protected function getOOUIModules() {
  90. return [ 'mediawiki.widgets.UserInputWidget' ];
  91. }
  92. public function getInputHtml( $value ) {
  93. // add the required module and css class for user suggestions in non-OOUI mode
  94. $this->mParent->getOutput()->addModules( 'mediawiki.userSuggest' );
  95. $this->mClass .= ' mw-autocomplete-user';
  96. // return parent html
  97. return parent::getInputHTML( $value );
  98. }
  99. }