Completed
Pull Request — master (#2)
by Stephen
13:19
created

Tests_User::test_search_users_email()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 0
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
// test functions in wp-includes/user.php
4
/**
5
 * @group user
6
 */
7
class Tests_User extends WP_UnitTestCase {
8
	protected static $admin_id;
9
	protected static $editor_id;
10
	protected static $author_id;
11
	protected static $contrib_id;
12
	protected static $sub_id;
13
14
	protected static $user_ids = array();
15
16
	protected static $_author;
17
	protected $author;
18
	protected $user_data;
19
20
	public static function wpSetUpBeforeClass( $factory ) {
21
		self::$user_ids[] = self::$contrib_id = $factory->user->create( array(
22
			'user_login' => 'user1',
23
			'user_nicename' => 'userone',
24
			'user_pass'  => 'password',
25
			'first_name' => 'John',
26
			'last_name'  => 'Doe',
27
			'display_name' => 'John Doe',
28
			'user_email' => '[email protected]',
29
			'user_url' => 'http://tacos.com',
30
			'role' => 'contributor'
31
		) );
32
33
		self::$user_ids[] = self::$author_id = $factory->user->create( array(
34
			'user_login' => 'author_login',
35
			'user_email' => '[email protected]',
36
			'role' => 'author'
37
		) );
38
39
		self::$user_ids[] = self::$admin_id = $factory->user->create( array( 'role' => 'administrator' ) );
40
		self::$user_ids[] = self::$editor_id = $factory->user->create( array(
41
			'role' => 'editor',
42
			'user_email' => '[email protected]',
43
		) );
44
		self::$user_ids[] = self::$sub_id = $factory->user->create( array( 'role' => 'subscriber' ) );
45
46
		self::$_author = get_user_by( 'ID', self::$author_id );
47
	}
48
49
	function setUp() {
50
		parent::setUp();
51
52
		$this->author = clone self::$_author;
53
	}
54
55
	function test_get_users_of_blog() {
56
		// add one of each user role
57
		$nusers = array(
58
			self::$contrib_id,
59
			self::$author_id,
60
			self::$admin_id,
61
			self::$editor_id,
62
			self::$sub_id,
63
		);
64
65
		$user_list = get_users();
66
67
		// find the role of each user as returned by get_users_of_blog
68
		$found = array();
69
		foreach ( $user_list as $user ) {
70
			// only include the users we just created - there might be some others that existed previously
71
			if ( in_array( $user->ID, $nusers ) ) {
72
				$found[] = $user->ID;
73
			}
74
		}
75
76
		// make sure every user we created was returned
77
		$this->assertEqualSets( $nusers, $found );
78
	}
79
80
	// simple get/set tests for user_option functions
81
	function test_user_option() {
82
		$key = rand_str();
83
		$val = rand_str();
84
85
		// get an option that doesn't exist
86
		$this->assertFalse( get_user_option( $key, self::$author_id ) );
87
88
		// set and get
89
		update_user_option( self::$author_id, $key, $val );
90
		$this->assertEquals( $val, get_user_option( $key, self::$author_id ) );
91
92
		// change and get again
93
		$val2 = rand_str();
94
		update_user_option( self::$author_id, $key, $val2 );
95
		$this->assertEquals( $val2, get_user_option( $key, self::$author_id ) );
96
	}
97
98
	// simple tests for usermeta functions
99
	function test_usermeta() {
100
		$key = 'key';
101
		$val = 'value1';
102
103
		// get a meta key that doesn't exist
104
		$this->assertEquals( '', get_user_meta( self::$author_id, $key, true ) );
105
106
		// set and get
107
		update_user_meta( self::$author_id, $key, $val );
108
		$this->assertEquals( $val, get_user_meta( self::$author_id, $key, true ) );
109
110
		// change and get again
111
		$val2 = 'value2';
112
		update_user_meta( self::$author_id, $key, $val2 );
113
		$this->assertEquals( $val2, get_user_meta( self::$author_id, $key, true ) );
114
115
		// delete and get
116
		delete_user_meta( self::$author_id, $key );
117
		$this->assertEquals( '', get_user_meta( self::$author_id, $key, true ) );
118
119
		// delete by key AND value
120
		update_user_meta( self::$author_id, $key, $val );
121
		// incorrect key: key still exists
122
		delete_user_meta( self::$author_id, $key, rand_str() );
123
		$this->assertEquals( $val, get_user_meta( self::$author_id, $key, true ) );
124
		// correct key: deleted
125
		delete_user_meta( self::$author_id, $key, $val );
126
		$this->assertEquals( '', get_user_meta( self::$author_id, $key, true ) );
127
128
	}
129
130
	// test usermeta functions in array mode
131
	function test_usermeta_array() {
132
		// some values to set
133
		$vals = array(
134
			rand_str() => 'val-'.rand_str(),
135
			rand_str() => 'val-'.rand_str(),
136
			rand_str() => 'val-'.rand_str(),
137
		);
138
139
		// there is already some stuff in the array
140
		$this->assertTrue( is_array( get_user_meta( self::$author_id ) ) );
141
142
		foreach ( $vals as $k => $v ) {
143
			update_user_meta( self::$author_id, $k, $v );
144
		}
145
		// get the complete usermeta array
146
		$out = get_user_meta( self::$author_id );
147
148
		// for reasons unclear, the resulting array is indexed numerically; meta keys are not included anywhere.
149
		// so we'll just check to make sure our values are included somewhere.
150
		foreach ( $vals as $k => $v ) {
151
			$this->assertTrue( isset( $out[$k] ) && $out[$k][0] == $v );
152
		}
153
		// delete one key and check again
154
		$keys = array_keys( $vals );
155
		$key_to_delete = array_pop( $keys );
156
		delete_user_meta( self::$author_id, $key_to_delete );
157
		$out = get_user_meta( self::$author_id );
158
		// make sure that key is excluded from the results
159
		foreach ($vals as $k=>$v) {
160
			if ($k == $key_to_delete) {
161
				$this->assertFalse( isset( $out[$k] ) );
162
			} else {
163
				$this->assertTrue( isset( $out[$k] ) && $out[$k][0] == $v );
164
			}
165
		}
166
	}
167
168
	// Test property magic functions for property get/set/isset.
169
	function test_user_properties() {
170
		$user = new WP_User( self::$author_id );
171
172
		foreach ( $user->data as $key => $data ) {
173
			$this->assertEquals( $data, $user->$key );
174
		}
175
176
		$this->assertTrue( isset( $user->$key ) );
0 ignored issues
show
Bug introduced by
The variable $key seems to be defined by a foreach iteration on line 172. Are you sure the iterator is never empty, otherwise this variable is not defined?

It seems like you are relying on a variable being defined by an iteration:

foreach ($a as $b) {
}

// $b is defined here only if $a has elements, for example if $a is array()
// then $b would not be defined here. To avoid that, we recommend to set a
// default value for $b.


// Better
$b = 0; // or whatever default makes sense in your context
foreach ($a as $b) {
}

// $b is now guaranteed to be defined here.
Loading history...
177
		$this->assertFalse( isset( $user->fooooooooo ) );
178
179
		$user->$key = 'foo';
180
		$this->assertEquals( 'foo', $user->$key );
181
		$this->assertEquals( 'foo', $user->data->$key );  // This will fail with WP < 3.3
182
183
		foreach ( (array) $user as $key => $value ) {
184
			$this->assertEquals( $value, $user->$key );
185
		}
186
	}
187
188
	/**
189
	 * Test the magic __unset method
190
	 *
191
	 * @ticket 20043
192
	 */
193
	public function test_user_unset() {
194
		$user = new WP_User( self::$author_id );
195
196
		// Test custom fields
197
		$user->customField = 123;
0 ignored issues
show
Documentation introduced by
The property customField does not exist on object<WP_User>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
198
		$this->assertEquals( $user->customField, 123 );
0 ignored issues
show
Documentation introduced by
The property customField does not exist on object<WP_User>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
199
		unset( $user->customField );
200
		$this->assertFalse( isset( $user->customField ) );
201
		return $user;
202
	}
203
204
	/**
205
	 * @depends test_user_unset
206
	 * @expectedDeprecated WP_User->id
207
	 * @ticket 20043
208
	 */
209
	function test_user_unset_lowercase_id( $user ) {
210
		// Test 'id' (lowercase)
211
		$id = $user->id;
212
		unset( $user->id );
213
		$this->assertSame( $id, $user->id );
214
		return $user;
215
	}
216
217
	/**
218
	 * @depends test_user_unset_lowercase_id
219
	 * @ticket 20043
220
	 */
221
	function test_user_unset_uppercase_id( $user ) {
222
		// Test 'ID'
223
		$this->assertNotEmpty( $user->ID );
224
		unset( $user->ID );
225
		$this->assertNotEmpty( $user->ID );
226
	}
227
228
	// Test meta property magic functions for property get/set/isset.
229
	function test_user_meta_properties() {
230
		$user = new WP_User( self::$author_id );
231
232
		update_user_option( self::$author_id, 'foo', 'foo', true );
233
234
		$this->assertTrue( isset( $user->foo ) );
235
236
		$this->assertEquals( 'foo', $user->foo );
0 ignored issues
show
Documentation introduced by
The property foo does not exist on object<WP_User>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
237
	}
238
239
	/**
240
	 * @expectedDeprecated WP_User->id
241
	 */
242
	function test_id_property_back_compat() {
243
		$user = new WP_User( self::$author_id );
244
245
		$this->assertTrue( isset( $user->id ) );
246
		$this->assertEquals( $user->ID, $user->id );
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<WP_User>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
247
		$user->id = 1234;
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<WP_User>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
248
		$this->assertEquals( $user->ID, $user->id );
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<WP_User>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
249
	}
250
251
	/**
252
	 * ticket 19265
253
	 */
254
	function test_user_level_property_back_compat() {
255
		$roles = array(
256
			self::$admin_id => 10,
257
			self::$editor_id => 7,
258
			self::$author_id => 2,
259
			self::$contrib_id => 1,
260
			self::$sub_id => 0,
261
		);
262
263
		foreach ( $roles as $user_id => $level ) {
264
			$user = new WP_User( $user_id );
265
266
			$this->assertTrue( isset( $user->user_level ) );
267
			$this->assertEquals( $level, $user->user_level );
268
		}
269
	}
270
271
	function test_construction() {
272
		$user = new WP_User( self::$author_id );
273
		$this->assertInstanceOf( 'WP_User', $user );
274
		$this->assertEquals( self::$author_id, $user->ID );
275
276
		$user2 = new WP_User( 0,  $user->user_login );
277
		$this->assertInstanceOf( 'WP_User', $user2 );
278
		$this->assertEquals( self::$author_id, $user2->ID );
279
		$this->assertEquals( $user->user_login, $user2->user_login );
280
281
		$user3 = new WP_User();
282
		$this->assertInstanceOf( 'WP_User', $user3 );
283
		$this->assertEquals( 0, $user3->ID );
284
		$this->assertFalse( isset( $user3->user_login ) );
285
286
		$user3->init( $user->data );
287
		$this->assertEquals( self::$author_id, $user3->ID );
288
289
		$user4 = new WP_User( $user->user_login );
290
		$this->assertInstanceOf( 'WP_User', $user4 );
291
		$this->assertEquals( self::$author_id, $user4->ID );
292
		$this->assertEquals( $user->user_login, $user4->user_login );
293
294
		$user5 = new WP_User( null, $user->user_login );
295
		$this->assertInstanceOf( 'WP_User', $user5 );
296
		$this->assertEquals( self::$author_id, $user5->ID );
297
		$this->assertEquals( $user->user_login, $user5->user_login );
298
299
		$user6 = new WP_User( $user );
0 ignored issues
show
Documentation introduced by
$user is of type object<WP_User>, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
300
		$this->assertInstanceOf( 'WP_User', $user6 );
301
		$this->assertEquals( self::$author_id, $user6->ID );
302
		$this->assertEquals( $user->user_login, $user6->user_login );
303
304
		$user7 = new WP_User( $user->data );
0 ignored issues
show
Documentation introduced by
$user->data is of type object, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
305
		$this->assertInstanceOf( 'WP_User', $user7 );
306
		$this->assertEquals( self::$author_id, $user7->ID );
307
		$this->assertEquals( $user->user_login, $user7->user_login );
308
	}
309
310
	function test_get() {
311
		$user = new WP_User( self::$author_id );
312
		$this->assertEquals( 'author_login', $user->get( 'user_login' ) );
313
		$this->assertEquals( '[email protected]', $user->get( 'user_email' ) );
314
		$this->assertEquals( 0, $user->get( 'use_ssl' ) );
315
		$this->assertEquals( '', $user->get( 'field_that_does_not_exist' ) );
316
317
		update_user_meta( self::$author_id, 'dashed-key', 'abcdefg' );
318
		$this->assertEquals( 'abcdefg', $user->get( 'dashed-key' ) );
319
	}
320
321
	function test_has_prop() {
322
		$user = new WP_User( self::$author_id );
323
		$this->assertTrue( $user->has_prop( 'user_email') );
324
		$this->assertTrue( $user->has_prop( 'use_ssl' ) );
325
		$this->assertFalse( $user->has_prop( 'field_that_does_not_exist' ) );
326
327
		update_user_meta( self::$author_id, 'dashed-key', 'abcdefg' );
328
		$this->assertTrue( $user->has_prop( 'dashed-key' ) );
329
	}
330
331
	function test_update_user() {
332
		$user = new WP_User( self::$author_id );
333
334
		update_user_meta( self::$author_id, 'description', 'about me' );
335
		$this->assertEquals( 'about me', $user->get( 'description' ) );
336
337
		$user_data = array( 'ID' => self::$author_id, 'display_name' => 'test user' );
338
		wp_update_user( $user_data );
339
340
		$user = new WP_User( self::$author_id );
341
		$this->assertEquals( 'test user', $user->get( 'display_name' ) );
342
343
		// Make sure there is no collateral damage to fields not in $user_data
344
		$this->assertEquals( 'about me', $user->get( 'description' ) );
345
346
		// Pass as stdClass
347
		$user_data = array( 'ID' => self::$author_id, 'display_name' => 'a test user' );
348
		wp_update_user( (object) $user_data );
349
350
		$user = new WP_User( self::$author_id );
351
		$this->assertEquals( 'a test user', $user->get( 'display_name' ) );
352
353
		$user->display_name = 'some test user';
354
		wp_update_user( $user );
355
356
		$this->assertEquals( 'some test user', $user->get( 'display_name' ) );
357
358
		// Test update of fields in _get_additional_user_keys()
359
		$user_data = array(
360
			'ID' => self::$author_id, 'use_ssl' => 1, 'show_admin_bar_front' => 1,
361
			'rich_editing' => 1, 'first_name' => 'first', 'last_name' => 'last',
362
			'nickname' => 'nick', 'comment_shortcuts' => 'true', 'admin_color' => 'classic',
363
			'description' => 'describe'
364
		);
365
		wp_update_user( $user_data );
366
367
		$user = new WP_User( self::$author_id );
368
		foreach ( $user_data as $key => $value ) {
369
			$this->assertEquals( $value, $user->get( $key ), $key );
370
		}
371
	}
372
373
	/**
374
	 * ticket 19595
375
	 */
376
	function test_global_userdata() {
377
		global $userdata, $wpdb;
378
379
		wp_set_current_user( self::$sub_id );
380
381
		$this->assertNotEmpty( $userdata );
382
		$this->assertInstanceOf( 'WP_User', $userdata );
383
		$this->assertEquals( $userdata->ID, self::$sub_id );
384
		$prefix = $wpdb->get_blog_prefix();
385
		$cap_key = $prefix . 'capabilities';
386
		$this->assertTrue( isset( $userdata->$cap_key ) );
387
	}
388
389
	/**
390
	 * ticket 19769
391
	 */
392
	function test_global_userdata_is_null_when_logged_out() {
393
		global $userdata;
394
		wp_set_current_user( 0 );
395
		$this->assertNull( $userdata );
396
	}
397
398
	function test_exists() {
399
		$user = new WP_User( self::$author_id );
400
401
		$this->assertTrue( $user->exists() );
402
403
		$user = new WP_User( 123456789 );
404
405
		$this->assertFalse( $user->exists() );
406
407
		$user = new WP_User( 0 );
408
409
		$this->assertFalse( $user->exists() );
410
	}
411
412
	function test_global_authordata() {
413
		global $authordata, $id;
414
415
		$old_post_id = $id;
416
417
		$user = new WP_User( self::$author_id );
0 ignored issues
show
Unused Code introduced by
$user is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
418
419
		$post = array(
420
			'post_author' => self::$author_id,
421
			'post_status' => 'publish',
422
			'post_content' => rand_str(),
423
			'post_title' => rand_str(),
424
			'post_type' => 'post'
425
		);
426
427
		// insert a post and make sure the ID is ok
428
		$post_id = wp_insert_post( $post );
429
		$this->assertTrue( is_numeric( $post_id ) );
430
431
		setup_postdata( get_post( $post_id ) );
0 ignored issues
show
Bug introduced by
It seems like get_post($post_id) targeting get_post() can also be of type array or null; however, setup_postdata() does only seem to accept object|integer, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
432
433
		$this->assertNotEmpty( $authordata );
434
		$this->assertInstanceOf( 'WP_User', $authordata );
435
		$this->assertEquals( $authordata->ID, self::$author_id );
436
437
		if ( $old_post_id ) {
438
			setup_postdata( get_post( $old_post_id ) );
0 ignored issues
show
Bug introduced by
It seems like get_post($old_post_id) targeting get_post() can also be of type array or null; however, setup_postdata() does only seem to accept object|integer, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
439
		}
440
	}
441
442
	/**
443
	 * @ticket 13317
444
	 */
445
	function test_get_userdata() {
446
		$this->assertFalse( get_userdata( 0 ) );
447
		$this->assertFalse( get_userdata( '0' ) );
448
		$this->assertFalse( get_userdata( 'string' ) );
449
		$this->assertFalse( get_userdata( array( 'array' ) ) );
0 ignored issues
show
Documentation introduced by
array('array') is of type array<integer,string,{"0":"string"}>, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
450
	}
451
452
	function test_user_get_data_by_id() {
453
		$user = WP_User::get_data_by( 'id', self::$author_id );
454
		$this->assertInstanceOf( 'stdClass', $user );
455
		$this->assertEquals( self::$author_id, $user->ID );
456
457
		// @ticket 23480
458
		$user1 = WP_User::get_data_by( 'id', -1 );
459
		$this->assertEquals( false, $user1 );
460
461
		$user2 = WP_User::get_data_by( 'id', 0 );
462
		$this->assertEquals( false, $user2 );
463
464
		$user3 = WP_User::get_data_by( 'id', null );
465
		$this->assertEquals( false, $user3 );
466
467
		$user4 = WP_User::get_data_by( 'id', '' );
468
		$this->assertEquals( false, $user4 );
469
470
		$user5 = WP_User::get_data_by( 'id', false );
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string|integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
471
		$this->assertEquals( false, $user5 );
472
473
		$user6 = WP_User::get_data_by( 'id', $user->user_nicename );
474
		$this->assertEquals( false, $user6 );
475
476
		$user7 = WP_User::get_data_by( 'id', 99999 );
477
		$this->assertEquals( false, $user7 );
478
	}
479
480
	/**
481
	 * @ticket 33869
482
	 */
483
	public function test_user_get_data_by_ID_should_alias_to_id() {
484
		$user = WP_User::get_data_by( 'ID', self::$author_id );
485
		$this->assertEquals( self::$author_id, $user->ID );
486
	}
487
488
	/**
489
	 * @ticket 21431
490
	 */
491
	function test_count_many_users_posts() {
492
		$user_id_b = self::factory()->user->create( array( 'role' => 'author' ) );
493
		$post_id_a = self::factory()->post->create( array( 'post_author' => self::$author_id ) );
0 ignored issues
show
Unused Code introduced by
$post_id_a is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
494
		$post_id_b = self::factory()->post->create( array( 'post_author' => $user_id_b ) );
0 ignored issues
show
Unused Code introduced by
$post_id_b is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
495
		$post_id_c = self::factory()->post->create( array( 'post_author' => $user_id_b, 'post_status' => 'private' ) );
0 ignored issues
show
Unused Code introduced by
$post_id_c is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
496
497
		wp_set_current_user( self::$author_id );
498
		$counts = count_many_users_posts( array( self::$author_id, $user_id_b ), 'post', false );
499
		$this->assertEquals( 1, $counts[self::$author_id] );
500
		$this->assertEquals( 1, $counts[$user_id_b] );
501
502
		$counts = count_many_users_posts( array( self::$author_id, $user_id_b ), 'post', true );
503
		$this->assertEquals( 1, $counts[self::$author_id] );
504
		$this->assertEquals( 1, $counts[$user_id_b] );
505
506
		wp_set_current_user( $user_id_b );
507
		$counts = count_many_users_posts( array( self::$author_id, $user_id_b ), 'post', false );
508
		$this->assertEquals( 1, $counts[self::$author_id] );
509
		$this->assertEquals( 2, $counts[$user_id_b] );
510
511
		$counts = count_many_users_posts( array( self::$author_id, $user_id_b ), 'post', true );
512
		$this->assertEquals( 1, $counts[self::$author_id] );
513
		$this->assertEquals( 1, $counts[$user_id_b] );
514
	}
515
516
	/**
517
	 * @ticket 22858
518
	 */
519
	function test_wp_update_user_on_nonexistent_users() {
520
		$user_id = 1;
521
		// Find me a non-existent user ID.
522
		while ( get_userdata( $user_id ) )
523
			++$user_id;
524
525
		// If this test fails, it will error out for calling the to_array() method on a non-object.
526
		$this->assertInstanceOf( 'WP_Error', wp_update_user( array( 'ID' => $user_id ) ) );
527
	}
528
529
	/**
530
	 * @ticket 28435
531
	 */
532
	function test_wp_update_user_should_not_change_password_when_passed_WP_User_instance() {
533
		$testuserid = 1;
534
		$user = get_userdata( $testuserid );
535
		$pwd_before = $user->user_pass;
536
		wp_update_user( $user );
537
538
		// Reload the data
539
		$pwd_after = get_userdata( $testuserid )->user_pass;
540
		$this->assertEquals( $pwd_before, $pwd_after );
541
	}
542
543
	/**
544
	 * @ticket 28315
545
	 */
546
	function test_user_meta_error() {
547
		$id1 = wp_insert_user( array(
548
			'user_login' => rand_str(),
549
			'user_pass' => 'password',
550
			'user_email' => '[email protected]',
551
		) );
552
		$this->assertEquals( $id1, email_exists( '[email protected]' ) );
553
554
		$id2 = wp_insert_user( array(
555
			'user_login' => rand_str(),
556
			'user_pass' => 'password',
557
			'user_email' => '[email protected]',
558
		) );
559
560
		if ( ! defined( 'WP_IMPORTING' ) ) {
561
			$this->assertWPError( $id2 );
562
		}
563
564
		@update_user_meta( $id2, 'key', 'value' );
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
565
566
		$metas = array_keys( get_user_meta( 1 ) );
567
		$this->assertNotContains( 'key', $metas );
568
	}
569
570
	/**
571
	 * @ticket 30647
572
	 */
573
	function test_user_update_email_error() {
574
		$id1 = wp_insert_user( array(
575
			'user_login' => 'blackburn',
576
			'user_pass'  => 'password',
577
			'user_email' => '[email protected]',
578
		) );
579
		$this->assertEquals( $id1, email_exists( '[email protected]' ) );
580
581
		$id2 = wp_insert_user( array(
582
			'user_login' => 'miller',
583
			'user_pass'  => 'password',
584
			'user_email' => '[email protected]',
585
		) );
586
		$this->assertEquals( $id2, email_exists( '[email protected]' ) );
587
588
		if ( ! is_wp_error( $id2 ) ){
589
			wp_update_user( array(
590
				'ID'         => $id2,
591
				'user_email' => '[email protected]',
592
			) );
593
			$this->assertEquals( $id2, email_exists( '[email protected]' ) );
594
595
			$return = wp_update_user( array(
596
				'ID'         => $id2,
597
				'user_email' => '[email protected]',
598
			) );
599
600
			if ( ! defined( 'WP_IMPORTING' ) ) {
601
				$this->assertWPError( $return );
602
			}
603
		}
604
	}
605
606
	/**
607
	 * @ticket 27317
608
	 * @dataProvider _illegal_user_logins_data
609
	 */
610
	function test_illegal_user_logins_single( $user_login ) {
611
		$user_data = array(
612
			'user_login' => $user_login,
613
			'user_email' => '[email protected]',
614
			'user_pass'  => wp_generate_password(),
615
		);
616
617
		add_filter( 'illegal_user_logins', array( $this, '_illegal_user_logins' ) );
618
619
		$response = wp_insert_user( $user_data );
620
		$this->assertInstanceOf( 'WP_Error', $response );
621
		$this->assertEquals( 'invalid_username', $response->get_error_code() );
622
623
		remove_filter( 'illegal_user_logins', array( $this, '_illegal_user_logins' ) );
624
625
		$user_id = wp_insert_user( $user_data );
626
		$user = get_user_by( 'id', $user_id );
627
		$this->assertInstanceOf( 'WP_User', $user );
628
	}
629
630
	/**
631
	 * @ticket 27317
632
	 * @dataProvider _illegal_user_logins_data
633
	 */
634
	function test_illegal_user_logins_single_wp_create_user( $user_login ) {
635
		$user_email = 'testuser-' . $user_login . '@example.com';
636
637
		add_filter( 'illegal_user_logins', array( $this, '_illegal_user_logins' ) );
638
639
		$response = register_new_user( $user_login, $user_email );
640
		$this->assertInstanceOf( 'WP_Error', $response );
641
		$this->assertEquals( 'invalid_username', $response->get_error_code() );
642
643
		remove_filter( 'illegal_user_logins', array( $this, '_illegal_user_logins' ) );
644
645
		$response = register_new_user( $user_login, $user_email );
646
		$user = get_user_by( 'id', $response );
647
		$this->assertInstanceOf( 'WP_User', $user );
648
	}
649
650
	/**
651
	 * @ticket 27317
652
	 * @group ms-required
653
	 */
654
	function test_illegal_user_logins_multisite() {
655
		$user_data = array(
656
			'user_login' => 'testuser',
657
			'user_email' => '[email protected]',
658
		);
659
660
		add_filter( 'illegal_user_logins', array( $this, '_illegal_user_logins' ) );
661
662
		$response = wpmu_validate_user_signup( $user_data['user_login'], $user_data['user_email'] );
663
		$this->assertInstanceOf( 'WP_Error', $response['errors'] );
664
		$this->assertEquals( 'user_name', $response['errors']->get_error_code() );
665
666
		remove_filter( 'illegal_user_logins', array( $this, '_illegal_user_logins' ) );
667
668
		$response = wpmu_validate_user_signup( $user_data['user_login'], $user_data['user_email'] );
669
		$this->assertInstanceOf( 'WP_Error', $response['errors'] );
670
		$this->assertEquals( 0, count( $response['errors']->get_error_codes() ) );
671
	}
672
673
	function _illegal_user_logins_data() {
674
		$data = array(
675
			array( 'testuser' )
676
		);
677
678
		// Multisite doesn't allow mixed case logins ever
679
		if ( ! is_multisite() ) {
680
			$data[] = array( 'TestUser' );
681
		}
682
		return $data;
683
	}
684
685
	function _illegal_user_logins() {
686
		return array( 'testuser' );
687
	}
688
689
	/**
690
	 * @ticket 24618
691
	 */
692
	public function test_validate_username_string() {
693
		$this->assertTrue( validate_username( 'johndoe' ) );
694
		$this->assertTrue( validate_username( '[email protected]' ) );
695
	}
696
697
	/**
698
	 * @ticket 24618
699
	 */
700
	public function test_validate_username_contains_uppercase_letters() {
701
		if ( is_multisite() ) {
702
			$this->assertFalse( validate_username( 'JohnDoe' ) );
703
		} else {
704
			$this->assertTrue( validate_username( 'JohnDoe' ) );
705
		}
706
	}
707
708
	/**
709
	 * @ticket 24618
710
	 */
711
	public function test_validate_username_empty() {
712
		$this->assertFalse( validate_username( '' ) );
713
	}
714
715
	/**
716
	 * @ticket 24618
717
	 */
718
	public function test_validate_username_invalid() {
719
		$this->assertFalse( validate_username( '@#&99sd' ) );
720
	}
721
722
 	/**
0 ignored issues
show
Coding Style introduced by
There is some trailing whitespace on this line which should be avoided as per coding-style.
Loading history...
723
	 * @ticket 29880
724
	 */
725
	public function test_wp_insert_user_should_not_wipe_existing_password() {
726
		$user_details = array(
727
			'user_login' => rand_str(),
728
			'user_pass' => 'password',
729
			'user_email' => rand_str() . '@example.com',
730
		);
731
732
		$user_id = wp_insert_user( $user_details );
733
		$this->assertEquals( $user_id, email_exists( $user_details['user_email'] ) );
734
735
		// Check that providing an empty password doesn't remove a user's password.
736
		$user_details['ID'] = $user_id;
737
		$user_details['user_pass'] = '';
738
739
		$user_id = wp_insert_user( $user_details );
740
		$user = WP_User::get_data_by( 'id', $user_id );
741
		$this->assertNotEmpty( $user->user_pass );
742
	}
743
744
	/**
745
	 * @ticket 29696
746
	 */
747
	public function test_wp_insert_user_should_sanitize_user_nicename_parameter() {
748
		$user = $this->author;
749
750
		$userdata = $user->to_array();
751
		$userdata['user_nicename'] = str_replace( '-', '.', $user->user_nicename );
752
		wp_insert_user( $userdata );
753
754
		$updated_user = new WP_User( $user->ID );
755
756
		$this->assertSame( $user->user_nicename, $updated_user->user_nicename );
757
	}
758
759
	/**
760
	 * @ticket 33793
761
	 */
762
	public function test_wp_insert_user_should_accept_user_login_with_60_characters() {
763
		$user_login = str_repeat( 'a', 60 );
764
		$u = wp_insert_user( array(
765
			'user_login' => $user_login,
766
			'user_email' => $user_login . '@example.com',
767
			'user_pass' => 'password',
768
			'user_nicename' => 'something-short',
769
		) );
770
771
		$this->assertInternalType( 'int', $u );
772
		$this->assertGreaterThan( 0, $u );
773
774
		$user = new WP_User( $u );
775
		$this->assertSame( $user_login, $user->user_login );
776
	}
777
778
	/**
779
	 * @ticket 33793
780
	 */
781
	public function test_wp_insert_user_should_reject_user_login_over_60_characters() {
782
		$user_login = str_repeat( 'a', 61 );
783
		$u = wp_insert_user( array(
784
			'user_login' => $user_login,
785
			'user_email' => $user_login . '@example.com',
786
			'user_pass' => 'password',
787
			'user_nicename' => 'something-short',
788
		) );
789
790
		$this->assertWPError( $u );
791
		$this->assertSame( 'user_login_too_long', $u->get_error_code() );
792
	}
793
794
	/**
795
	 * @ticket 33793
796
	 */
797
	public function test_wp_insert_user_should_reject_user_nicename_over_50_characters() {
798
		$user_nicename = str_repeat( 'a', 51 );
799
		$u = wp_insert_user( array(
800
			'user_login' => 'mynicenamehas50chars',
801
			'user_email' => $user_nicename . '@example.com',
802
			'user_pass' => 'password',
803
			'user_nicename' => $user_nicename,
804
		) );
805
806
		$this->assertWPError( $u );
807
		$this->assertSame( 'user_nicename_too_long', $u->get_error_code() );
808
	}
809
810
	/**
811
	 * @ticket 33793
812
	 */
813
	public function test_wp_insert_user_should_not_generate_user_nicename_longer_than_50_chars() {
814
		$user_login = str_repeat( 'a', 55 );
815
		$u = wp_insert_user( array(
816
			'user_login' => $user_login,
817
			'user_email' => $user_login . '@example.com',
818
			'user_pass' => 'password',
819
		) );
820
821
		$this->assertNotEmpty( $u );
822
		$user = new WP_User( $u );
823
		$expected = str_repeat( 'a', 50 );
824
		$this->assertSame( $expected, $user->user_nicename );
825
	}
826
827
	/**
828
	 * @ticket 33793
829
	 */
830
	public function test_wp_insert_user_should_not_truncate_to_a_duplicate_user_nicename() {
831
		$u1 = self::factory()->user->create( array(
832
			'user_nicename' => str_repeat( 'a', 50 ),
833
		) );
834
835
		$user1 = new WP_User( $u1 );
836
837
		$expected = str_repeat( 'a', 50 );
838
		$this->assertSame( $expected, $user1->user_nicename );
839
840
		$user_login = str_repeat( 'a', 55 );
841
		$u = wp_insert_user( array(
842
			'user_login' => $user_login,
843
			'user_email' => $user_login . '@example.com',
844
			'user_pass' => 'password',
845
		) );
846
847
		$this->assertNotEmpty( $u );
848
		$user2 = new WP_User( $u );
849
		$expected = str_repeat( 'a', 48 ) . '-2';
850
		$this->assertSame( $expected, $user2->user_nicename );
851
	}
852
853
	/**
854
	 * @ticket 33793
855
	 */
856
	public function test_wp_insert_user_should_not_truncate_to_a_duplicate_user_nicename_when_suffix_has_more_than_one_character() {
857
		$user_ids = self::factory()->user->create_many( 4, array(
858
			'user_nicename' => str_repeat( 'a', 50 ),
859
		) );
860
861
		foreach ( $user_ids as $i => $user_id ) {
862
			$user = new WP_User( $user_id );
863
			if ( 0 === $i ) {
864
				$expected = str_repeat( 'a', 50 );
865
			} else {
866
				$expected = str_repeat( 'a', 48 ) . '-' . ( $i + 1 );
867
			}
868
			$this->assertSame( $expected, $user->user_nicename );
869
		}
870
871
		$user_login = str_repeat( 'a', 55 );
872
		$u = wp_insert_user( array(
873
			'user_login' => $user_login,
874
			'user_email' => $user_login . '@example.com',
875
			'user_pass' => 'password',
876
		) );
877
878
		$this->assertNotEmpty( $u );
879
		$user = new WP_User( $u );
880
		$expected = str_repeat( 'a', 48 ) . '-5';
881
		$this->assertSame( $expected, $user->user_nicename );
882
	}
883
884
	/**
885
	 * @ticket 28004
886
	 */
887
	public function test_wp_insert_user_with_invalid_user_id() {
888
		global $wpdb;
889
		$max_user = $wpdb->get_var( "SELECT MAX(ID) FROM $wpdb->users" );
890
891
		$u = wp_insert_user( array(
892
			'ID' => $max_user + 1,
893
			'user_login' => 'whatever',
894
			'user_email' => '[email protected]',
895
			'user_pass' => 'password',
896
		) );
897
898
		$this->assertWPError( $u );
899
	}
900
901
	/**
902
	 * @ticket 35750
903
	 */
904
	public function test_wp_update_user_should_delete_userslugs_cache() {
905
		$u = self::factory()->user->create();
906
		$user = get_userdata( $u );
907
908
		wp_update_user( array(
909
			'ID' => $u,
910
			'user_nicename' => 'newusernicename',
911
		) );
912
		$updated_user = get_userdata( $u );
913
914
		$this->assertFalse( wp_cache_get( $user->user_nicename, 'userslugs' ) );
915
		$this->assertEquals( $u, wp_cache_get( $updated_user->user_nicename, 'userslugs' ) );
916
	}
917
918
	function test_changing_email_invalidates_password_reset_key() {
919
		global $wpdb;
920
921
		$user = $this->author;
922
		$wpdb->update( $wpdb->users, array( 'user_activation_key' => 'key' ), array( 'ID' => $user->ID ) );
923
		clean_user_cache( $user );
0 ignored issues
show
Security Bug introduced by
It seems like $user defined by $this->author on line 921 can also be of type false; however, clean_user_cache() does only seem to accept object<WP_User>|integer, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
924
925
		$user = get_userdata( $user->ID );
926
		$this->assertEquals( 'key', $user->user_activation_key );
927
928
		// Check that changing something other than the email doesn't remove the key.
929
		$userdata = array(
930
			'ID'            => $user->ID,
931
			'user_nicename' => 'wat',
932
		);
933
		wp_update_user( $userdata );
934
935
		$user = get_userdata( $user->ID );
936
		$this->assertEquals( 'key', $user->user_activation_key );
937
938
		// Now check that changing the email does remove it.
939
		$userdata = array(
940
			'ID'            => $user->ID,
941
			'user_nicename' => 'cat',
942
			'user_email'    => '[email protected]',
943
		);
944
		wp_update_user( $userdata );
945
946
		$user = get_userdata( $user->ID );
947
		$this->assertEmpty( $user->user_activation_key );
948
	}
949
950
	public function test_search_users_login() {
951
		$users = get_users( array( 'search' => 'user1', 'fields' => 'ID' ) );
952
953
		$this->assertTrue( in_array( self::$contrib_id, $users ) );
954
	}
955
956
	public function test_search_users_url() {
957
		$users = get_users( array( 'search' => '*tacos*', 'fields' => 'ID' ) );
958
959
		$this->assertTrue( in_array( self::$contrib_id, $users ) );
960
	}
961
962
	public function test_search_users_email() {
963
		$users = get_users( array( 'search' => '*battle*', 'fields' => 'ID' ) );
964
965
		$this->assertTrue( in_array( self::$contrib_id, $users ) );
966
	}
967
968
	public function test_search_users_nicename() {
969
		$users = get_users( array( 'search' => '*one*', 'fields' => 'ID' ) );
970
971
		$this->assertTrue( in_array( self::$contrib_id, $users ) );
972
	}
973
974
	public function test_search_users_display_name() {
975
		$users = get_users( array( 'search' => '*Doe*', 'fields' => 'ID' ) );
976
977
		$this->assertTrue( in_array( self::$contrib_id, $users ) );
978
	}
979
980
	/**
981
	 * @ticket 32158
982
	 */
983
	function test_email_case() {
984
		// Alter the case of the email address (which stays the same).
985
		$userdata = array(
986
			'ID' => self::$editor_id,
987
			'user_email' => '[email protected]',
988
		);
989
		$update = wp_update_user( $userdata );
990
991
		$this->assertEquals( self::$editor_id, $update );
992
	}
993
994
	/**
995
	 * @ticket 32158
996
	 */
997
	function test_email_change() {
998
		// Change the email address.
999
		$userdata = array(
1000
			'ID' => self::$editor_id,
1001
			'user_email' => '[email protected]',
1002
		);
1003
		$update = wp_update_user( $userdata );
1004
1005
		// Was this successful?
1006
		$this->assertEquals( self::$editor_id, $update );
1007
1008
		// Verify that the email address has been updated.
1009
		$user = get_userdata( self::$editor_id );
1010
		$this->assertEquals( $user->user_email, '[email protected]' );
1011
	}
1012
1013
	/**
1014
	 * Testing wp_new_user_notification email statuses.
1015
	 *
1016
	 * @dataProvider data_wp_new_user_notifications
1017
	 * @ticket 33654
1018
	 * @ticket 36009
1019
	 */
1020
	function test_wp_new_user_notification( $notify, $admin_email_sent_expected, $user_email_sent_expected ) {
1021
		reset_phpmailer_instance();
1022
1023
		$was_admin_email_sent = false;
1024
		$was_user_email_sent = false;
1025
1026
		wp_new_user_notification( self::$contrib_id, null, $notify );
1027
1028
		$mailer = tests_retrieve_phpmailer_instance();
1029
1030
		/*
1031
		 * Check to see if a notification email was sent to the
1032
		 * post author `[email protected]` and and site admin `[email protected]`.
1033
		 */
1034
		$first_recipient = $mailer->get_recipient( 'to' );
1035
		if ( $first_recipient ) {
1036
			$was_admin_email_sent = WP_TESTS_EMAIL === $first_recipient->address;
1037
			$was_user_email_sent = '[email protected]' === $first_recipient->address;
1038
		}
1039
1040
		$second_recipient = $mailer->get_recipient( 'to', 1 );
1041
		if ( $second_recipient ) {
1042
			$was_user_email_sent = '[email protected]' === $second_recipient->address;
1043
		}
1044
1045
1046
		$this->assertSame( $admin_email_sent_expected, $was_admin_email_sent, 'Admin email result was not as expected in test_wp_new_user_notification' );
1047
		$this->assertSame( $user_email_sent_expected , $was_user_email_sent, 'User email result was not as expected in test_wp_new_user_notification' );
1048
	}
1049
1050
	/**
1051
	 * Data provider for test_wp_new_user_notification().
1052
	 *
1053
	 * Passes the three available options for the $notify parameter and the expected email
1054
	 * emails sent status as a bool.
1055
	 *
1056
	 * @return array {
1057
	 *     @type array {
1058
	 *         @type string $post_args               The arguments that will merged with the $_POST array.
1059
	 *         @type bool $admin_email_sent_expected The expected result of whether an email was sent to the admin.
1060
	 *         @type bool $user_email_sent_expected  The expected result of whether an email was sent to the user.
1061
	 *     }
1062
	 * }
1063
	 */
1064
	function data_wp_new_user_notifications() {
1065
		return array(
1066
			array(
1067
				'',
1068
				true,
1069
				false,
1070
			),
1071
			array(
1072
				'admin',
1073
				true,
1074
				false,
1075
			),
1076
			array(
1077
				'user',
1078
				false,
1079
				true,
1080
			),
1081
			array(
1082
				'both',
1083
				true,
1084
				true,
1085
			),
1086
		);
1087
	}
1088
1089
	/**
1090
	 * Set up a user and try sending a notification using the old, deprecated
1091
	 * function signature `wp_new_user_notification( $user, 'plaintext_password' );`.
1092
	 *
1093
	 * @ticket 33654
1094
	 * @expectedDeprecated wp_new_user_notification
1095
	 */
1096
	function test_wp_new_user_notification_old_signature_throws_deprecated_warning_but_sends() {
1097
		reset_phpmailer_instance();
1098
1099
		$was_admin_email_sent = false;
1100
		$was_user_email_sent = false;
1101
		wp_new_user_notification( self::$contrib_id, 'this_is_a_test_password' );
1102
1103
		/*
1104
		 * Check to see if a notification email was sent to the
1105
		 * post author `[email protected]` and and site admin `[email protected]`.
1106
		 */
1107
		if ( ! empty( $GLOBALS['phpmailer']->mock_sent ) ) {
1108
			$was_admin_email_sent = ( isset( $GLOBALS['phpmailer']->mock_sent[0] ) && WP_TESTS_EMAIL == $GLOBALS['phpmailer']->mock_sent[0]['to'][0][0] );
1109
			$was_user_email_sent = ( isset( $GLOBALS['phpmailer']->mock_sent[1] ) && '[email protected]' == $GLOBALS['phpmailer']->mock_sent[1]['to'][0][0] );
1110
		}
1111
1112
		$this->assertTrue( $was_admin_email_sent );
1113
		$this->assertTrue( $was_user_email_sent );
1114
	}
1115
1116
	/**
1117
	 * Set up a user and try sending a notification using `wp_new_user_notification( $user );`.
1118
	 *
1119
	 * @ticket 34377
1120
	 */
1121
	function test_wp_new_user_notification_old_signature_no_password() {
1122
		reset_phpmailer_instance();
1123
1124
		$was_admin_email_sent = false;
1125
		$was_user_email_sent = false;
1126
		wp_new_user_notification( self::$contrib_id );
1127
1128
		/*
1129
		 * Check to see if a notification email was sent to the
1130
		 * post author `[email protected]` and and site admin `[email protected]`.
1131
		 */
1132
		if ( ! empty( $GLOBALS['phpmailer']->mock_sent ) ) {
1133
			$was_admin_email_sent = ( isset( $GLOBALS['phpmailer']->mock_sent[0] ) && WP_TESTS_EMAIL == $GLOBALS['phpmailer']->mock_sent[0]['to'][0][0] );
1134
			$was_user_email_sent = ( isset( $GLOBALS['phpmailer']->mock_sent[1] ) && '[email protected]' == $GLOBALS['phpmailer']->mock_sent[1]['to'][0][0] );
1135
		}
1136
1137
		$this->assertTrue( $was_admin_email_sent );
1138
		$this->assertFalse( $was_user_email_sent );
1139
	}
1140
1141
	/**
1142
	 * Checks that calling edit_user() with no password returns an error when adding, and doesn't when updating.
1143
	 *
1144
	 * @ticket 35715
1145
	 */
1146
	function test_edit_user_blank_pw() {
1147
		$_POST = $_GET = $_REQUEST = array();
1148
		$_POST['role'] = 'subscriber';
1149
		$_POST['email'] = '[email protected]';
1150
		$_POST['user_login'] = 'user_login1';
1151
		$_POST['first_name'] = 'first_name1';
1152
		$_POST['last_name'] = 'last_name1';
1153
		$_POST['nickname'] = 'nickname1';
1154
		$_POST['display_name'] = 'display_name1';
1155
1156
		// Check new user with missing password.
1157
		$response = edit_user();
1158
1159
		$this->assertInstanceOf( 'WP_Error', $response );
1160
		$this->assertEquals( 'pass', $response->get_error_code() );
1161
1162
		// Check new user with password set.
1163
		$_POST['pass1'] = $_POST['pass2'] = 'password';
1164
1165
		$user_id = edit_user();
1166
		$user = get_user_by( 'ID', $user_id );
1167
1168
		$this->assertInternalType( 'int', $user_id );
1169
		$this->assertInstanceOf( 'WP_User', $user );
1170
		$this->assertEquals( 'nickname1', $user->nickname );
1171
1172
		// Check updating user with empty password.
1173
		$_POST['nickname'] = 'nickname_updated';
1174
		$_POST['pass1'] = $_POST['pass2'] = '';
1175
1176
		$user_id = edit_user( $user_id );
1177
1178
		$this->assertInternalType( 'int', $user_id );
1179
		$this->assertEquals( 'nickname_updated', $user->nickname );
1180
1181
		// Check updating user with missing second password.
1182
		$_POST['nickname'] = 'nickname_updated2';
1183
		$_POST['pass1'] = 'blank_pass2';
1184
		$_POST['pass2'] = '';
1185
1186
		$response = edit_user( $user_id );
1187
1188
		$this->assertInstanceOf( 'WP_Error', $response );
1189
		$this->assertEquals( 'pass', $response->get_error_code() );
1190
		$this->assertEquals( 'nickname_updated', $user->nickname );
1191
1192
		// Check updating user with empty password via `check_passwords` action.
1193
		add_action( 'check_passwords', array( $this, 'action_check_passwords_blank_pw' ), 10, 2 );
1194
		$user_id = edit_user( $user_id );
1195
		remove_action( 'check_passwords', array( $this, 'action_check_passwords_blank_pw' ) );
1196
1197
		$this->assertInternalType( 'int', $user_id );
1198
		$this->assertEquals( 'nickname_updated2', $user->nickname );
1199
	}
1200
1201
	/**
1202
	 * Check passwords action for test_edit_user_blank_pw().
1203
	 */
1204
	function action_check_passwords_blank_pw( $user_login, &$pass1 ) {
1205
		$pass1 = '';
1206
	}
1207
}
1208