diff --git a/src/wp-includes/user.php b/src/wp-includes/user.php index 41c6241ab067d..327981bd173a0 100644 --- a/src/wp-includes/user.php +++ b/src/wp-includes/user.php @@ -2209,6 +2209,44 @@ function wp_insert_user( $userdata ) { $userdata = get_object_vars( $userdata ); } elseif ( $userdata instanceof WP_User ) { $userdata = $userdata->to_array(); + } elseif ( $userdata instanceof Traversable ) { + $userdata = iterator_to_array( $userdata ); + } elseif ( $userdata instanceof ArrayAccess ) { + $userdata_obj = $userdata; + $userdata = array(); + foreach ( + array( + 'ID', + 'user_pass', + 'user_login', + 'user_nicename', + 'user_url', + 'user_email', + 'display_name', + 'nickname', + 'first_name', + 'last_name', + 'description', + 'rich_editing', + 'syntax_highlighting', + 'comment_shortcuts', + 'admin_color', + 'use_ssl', + 'user_registered', + 'user_activation_key', + 'spam', + 'show_admin_bar_front', + 'role', + 'locale', + 'meta_input', + ) as $key + ) { + if ( isset( $userdata_obj[ $key ] ) ) { + $userdata[ $key ] = $userdata_obj[ $key ]; + } + } + } else { + $userdata = (array) $userdata; } // Are we updating or creating? @@ -2244,7 +2282,7 @@ function wp_insert_user( $userdata ) { $user_pass = wp_hash_password( $userdata['user_pass'] ); } - $sanitized_user_login = sanitize_user( $userdata['user_login'], true ); + $sanitized_user_login = sanitize_user( $userdata['user_login'] ?? '', true ); /** * Filters a username after it has been sanitized. diff --git a/tests/phpunit/tests/user.php b/tests/phpunit/tests/user.php index 756f600f1ab52..cf2c11113050a 100644 --- a/tests/phpunit/tests/user.php +++ b/tests/phpunit/tests/user.php @@ -982,6 +982,144 @@ public function test_illegal_user_logins_single( $user_login ) { $this->assertInstanceOf( 'WP_User', $user ); } + /** + * @ticket 61175 + * @covers ::wp_insert_user + */ + public function test_wp_insert_user_with_null() { + // Note: $this->expectWarning() is deprecated and will be removed in PHPUnit 10. + $warnings = array(); + set_error_handler( + static function ( int $errno, string $errstr ) use ( &$warnings ) { + $warnings[] = compact( 'errno', 'errstr' ); + return true; + }, + E_USER_WARNING + ); + $user = wp_insert_user( null ); + restore_error_handler(); + + $this->assertWPError( $user ); + $this->assertSame( 'empty_user_login', $user->get_error_code() ); + } + + /** + * @ticket 61175 + * @covers ::wp_insert_user + */ + public function test_wp_insert_user_with_stdclass() { + $data = array( + 'user_login' => 'new-admin', + 'user_pass' => 'better-password', + ); + $user_id = wp_insert_user( (object) $data ); + $this->assertIsInt( $user_id, 'Expected user to be created.' ); + $user = new WP_User( $user_id ); + $this->assertSame( $data['user_login'], $user->user_login ); + } + + /** + * @ticket 61175 + * @covers ::wp_insert_user + */ + public function test_wp_insert_user_with_wp_user() { + $username = 'new-admin'; + $user = new WP_User(); + $user->user_login = $username; + $user->user_pass = 'better-password'; + + $user_id = wp_insert_user( $user ); + $this->assertIsInt( $user_id, 'Expected user to be created.' ); + $user = new WP_User( $user_id ); + $this->assertSame( $username, $user->user_login ); + } + + /** + * @ticket 61175 + * @covers ::wp_insert_user + */ + public function test_wp_insert_user_with_traversable() { + $internal_data = array( + 'user_login' => 'new-admin', + 'user_pass' => 'better-password', + ); + + $array_access_user = new class( $internal_data ) implements ArrayAccess, IteratorAggregate { + private array $data; + + public function __construct( array $data ) { + $this->data = $data; + } + + public function offsetExists( $offset ): bool { + return isset( $this->data[ $offset ] ); + } + + #[\ReturnTypeWillChange] + public function offsetGet( $offset ) { + return $this->data[ $offset ]; + } + + public function offsetSet( $offset, $value ): void { + $this->data[ $offset ] = $value; + } + + public function offsetUnset( $offset ): void { + unset( $this->data[ $offset ] ); + } + + public function getIterator(): ArrayIterator { + return new ArrayIterator( $this->data ); + } + }; + + $user_id = wp_insert_user( $array_access_user ); + $this->assertIsInt( $user_id, 'Expected user to be created.' ); + $user = new WP_User( $user_id ); + $this->assertSame( $internal_data['user_login'], $user->user_login ); + } + + /** + * @ticket 61175 + * @covers ::wp_insert_user + */ + public function test_wp_insert_user_with_only_array_access() { + $internal_data = array( + 'user_login' => 'new-admin', + 'user_pass' => 'better-password', + ); + + $array_access_user = new class( $internal_data ) implements ArrayAccess { + private array $data; + + public function __construct( array $data ) { + $this->data = $data; + } + + public function offsetExists( $offset ): bool { + return isset( $this->data[ $offset ] ); + } + + #[\ReturnTypeWillChange] + public function offsetGet( $offset ) { + return $this->data[ $offset ]; + } + + public function offsetSet( $offset, $value ): void { + $this->data[ $offset ] = $value; + } + + public function offsetUnset( $offset ): void { + unset( $this->data[ $offset ] ); + } + }; + + $user_id = wp_insert_user( $array_access_user ); + $this->assertIsInt( $user_id, 'Expected user to be created.' ); + $user = new WP_User( $user_id ); + $this->assertSame( $internal_data['user_login'], $user->user_login ); + } + /** * @ticket 27317 * @dataProvider data_illegal_user_logins