Skip to content

Commit 61f8a11

Browse files
committed
Fix wp_insert_user() so PHPStan won't hang
1 parent 77d9403 commit 61f8a11

3 files changed

Lines changed: 145 additions & 4 deletions

File tree

src/wp-includes/user.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2209,6 +2209,10 @@ function wp_insert_user( $userdata ) {
22092209
$userdata = get_object_vars( $userdata );
22102210
} elseif ( $userdata instanceof WP_User ) {
22112211
$userdata = $userdata->to_array();
2212+
} elseif ( $userdata instanceof Traversable ) {
2213+
$userdata = iterator_to_array( $userdata );
2214+
} elseif ( ! ( $userdata instanceof ArrayAccess ) ) {
2215+
$userdata = (array) $userdata;
22122216
}
22132217

22142218
// Are we updating or creating?
@@ -2244,7 +2248,7 @@ function wp_insert_user( $userdata ) {
22442248
$user_pass = wp_hash_password( $userdata['user_pass'] );
22452249
}
22462250

2247-
$sanitized_user_login = sanitize_user( $userdata['user_login'], true );
2251+
$sanitized_user_login = sanitize_user( $userdata['user_login'] ?? '', true );
22482252

22492253
/**
22502254
* Filters a username after it has been sanitized.
@@ -2560,7 +2564,7 @@ function wp_insert_user( $userdata ) {
25602564
$meta = apply_filters( 'insert_user_meta', $meta, $user, $update, $userdata );
25612565

25622566
$custom_meta = array();
2563-
if ( array_key_exists( 'meta_input', $userdata ) && is_array( $userdata['meta_input'] ) && ! empty( $userdata['meta_input'] ) ) {
2567+
if ( ! empty( $userdata['meta_input'] ) && is_array( $userdata['meta_input'] ) ) {
25642568
$custom_meta = $userdata['meta_input'];
25652569
}
25662570

tests/phpstan/base.neon

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,5 +141,3 @@ parameters:
141141
- ../../src/wp-includes/SimplePie
142142
- ../../src/wp-includes/sodium_compat
143143
- ../../src/wp-includes/Text
144-
# Setting `$metadata['user_pass'] = ''` (https://core.trac.wordpress.org/ticket/22114) causes PHPStan to hang
145-
- ../../src/wp-includes/user.php

tests/phpunit/tests/user.php

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -982,6 +982,145 @@ public function test_illegal_user_logins_single( $user_login ) {
982982
$this->assertInstanceOf( 'WP_User', $user );
983983
}
984984

985+
986+
/**
987+
* @ticket 61175
988+
* @covers ::wp_insert_user
989+
*/
990+
public function test_wp_insert_user_with_null() {
991+
// Note: $this->expectWarning() is deprecated and will be removed in PHPUnit 10.
992+
$warnings = array();
993+
set_error_handler(
994+
static function ( int $errno, string $errstr ) use ( &$warnings ) {
995+
$warnings[] = compact( 'errno', 'errstr' );
996+
return true;
997+
},
998+
E_USER_WARNING
999+
);
1000+
$user = wp_insert_user( null );
1001+
restore_error_handler();
1002+
1003+
$this->assertWPError( $user );
1004+
$this->assertSame( 'empty_user_login', $user->get_error_code() );
1005+
}
1006+
1007+
/**
1008+
* @ticket 61175
1009+
* @covers ::wp_insert_user
1010+
*/
1011+
public function test_wp_insert_user_with_stdclass() {
1012+
$data = array(
1013+
'user_login' => 'new-admin',
1014+
'user_pass' => 'better-password',
1015+
);
1016+
$user_id = wp_insert_user( (object) $data );
1017+
$this->assertIsInt( $user_id, 'Expected user to be created.' );
1018+
$user = new WP_User( $user_id );
1019+
$this->assertSame( $data['user_login'], $user->user_login );
1020+
}
1021+
1022+
/**
1023+
* @ticket 61175
1024+
* @covers ::wp_insert_user
1025+
*/
1026+
public function test_wp_insert_user_with_wp_user() {
1027+
$username = 'new-admin';
1028+
$user = new WP_User();
1029+
$user->user_login = $username;
1030+
$user->user_pass = 'better-password';
1031+
1032+
$user_id = wp_insert_user( $user );
1033+
$this->assertIsInt( $user_id, 'Expected user to be created.' );
1034+
$user = new WP_User( $user_id );
1035+
$this->assertSame( $username, $user->user_login );
1036+
}
1037+
1038+
/**
1039+
* @ticket 61175
1040+
* @covers ::wp_insert_user
1041+
*/
1042+
public function test_wp_insert_user_with_traversable() {
1043+
$internal_data = array(
1044+
'user_login' => 'new-admin',
1045+
'user_pass' => 'better-password',
1046+
);
1047+
1048+
$array_access_user = new class( $internal_data ) implements ArrayAccess, IteratorAggregate {
1049+
private array $data;
1050+
1051+
public function __construct( array $data ) {
1052+
$this->data = $data;
1053+
}
1054+
1055+
public function offsetExists( $offset ): bool {
1056+
return isset( $this->data[ $offset ] );
1057+
}
1058+
1059+
#[\ReturnTypeWillChange]
1060+
public function offsetGet( $offset ) {
1061+
return $this->data[ $offset ];
1062+
}
1063+
1064+
public function offsetSet( $offset, $value ): void {
1065+
$this->data[ $offset ] = $value;
1066+
}
1067+
1068+
public function offsetUnset( $offset ): void {
1069+
unset( $this->data[ $offset ] );
1070+
}
1071+
1072+
public function getIterator(): ArrayIterator {
1073+
return new ArrayIterator( $this->data );
1074+
}
1075+
};
1076+
1077+
$user_id = wp_insert_user( $array_access_user );
1078+
$this->assertIsInt( $user_id, 'Expected user to be created.' );
1079+
$user = new WP_User( $user_id );
1080+
$this->assertSame( $internal_data['user_login'], $user->user_login );
1081+
}
1082+
1083+
/**
1084+
* @ticket 61175
1085+
* @covers ::wp_insert_user
1086+
*/
1087+
public function test_wp_insert_user_with_only_array_access() {
1088+
$internal_data = array(
1089+
'user_login' => 'new-admin',
1090+
'user_pass' => 'better-password',
1091+
);
1092+
1093+
$array_access_user = new class( $internal_data ) implements ArrayAccess {
1094+
private array $data;
1095+
1096+
public function __construct( array $data ) {
1097+
$this->data = $data;
1098+
}
1099+
1100+
public function offsetExists( $offset ): bool {
1101+
return isset( $this->data[ $offset ] );
1102+
}
1103+
1104+
#[\ReturnTypeWillChange]
1105+
public function offsetGet( $offset ) {
1106+
return $this->data[ $offset ];
1107+
}
1108+
1109+
public function offsetSet( $offset, $value ): void {
1110+
$this->data[ $offset ] = $value;
1111+
}
1112+
1113+
public function offsetUnset( $offset ): void {
1114+
unset( $this->data[ $offset ] );
1115+
}
1116+
};
1117+
1118+
$user_id = wp_insert_user( $array_access_user );
1119+
$this->assertIsInt( $user_id, 'Expected user to be created.' );
1120+
$user = new WP_User( $user_id );
1121+
$this->assertSame( $internal_data['user_login'], $user->user_login );
1122+
}
1123+
9851124
/**
9861125
* @ticket 27317
9871126
* @dataProvider data_illegal_user_logins

0 commit comments

Comments
 (0)