1<?php
2
3use MediaWiki\MediaWikiServices;
4use MediaWiki\Permissions\UltimateAuthority;
5use MediaWiki\User\UserFactory;
6use MediaWiki\User\UserIdentityValue;
7use Wikimedia\IPUtils;
8
9/**
10 * @covers \MediaWiki\User\UserFactory
11 * @group Database
12 *
13 * @author DannyS712
14 */
15class UserFactoryTest extends MediaWikiIntegrationTestCase {
16
17	private function getUserFactory() {
18		return MediaWikiServices::getInstance()->getUserFactory();
19	}
20
21	public function testNewFromName() {
22		$name = 'UserFactoryTest1';
23
24		$factory = $this->getUserFactory();
25		$user = $factory->newFromName( $name );
26
27		$this->assertInstanceOf( User::class, $user );
28		$this->assertSame( $name, $user->getName() );
29	}
30
31	public function testNewAnonymous() {
32		$factory = $this->getUserFactory();
33		$anon = $factory->newAnonymous();
34		$this->assertInstanceOf( User::class, $anon );
35
36		$currentIp = IPUtils::sanitizeIP( $anon->getRequest()->getIP() );
37
38		// Unspecified name defaults to current user's IP address
39		$this->assertSame( $currentIp, $anon->getName() );
40
41		$name = '192.0.2.0';
42		$anonIpSpecified = $factory->newAnonymous( $name );
43		$this->assertSame( $name, $anonIpSpecified->getName() );
44	}
45
46	public function testNewFromId() {
47		$id = 98257;
48
49		$factory = $this->getUserFactory();
50		$user = $factory->newFromId( $id );
51
52		$this->assertInstanceOf( User::class, $user );
53		$this->assertSame( $id, $user->getId() );
54	}
55
56	public function testNewFromIdentity() {
57		$identity = new UserIdentityValue( 98257, __METHOD__ );
58
59		$factory = $this->getUserFactory();
60		$user = $factory->newFromUserIdentity( $identity );
61
62		$this->assertInstanceOf( User::class, $user );
63		$this->assertSame( $identity->getId(), $user->getId() );
64		$this->assertSame( $identity->getName(), $user->getName() );
65
66		// make sure instance caching happens
67		$this->assertSame( $user, $factory->newFromUserIdentity( $identity ) );
68
69		// make sure instance caching distingushes between IDs
70		$otherIdentity = new UserIdentityValue( 33245, __METHOD__ );
71		$this->assertNotSame( $user, $factory->newFromUserIdentity( $otherIdentity ) );
72	}
73
74	public function testNewFromActorId() {
75		$name = 'UserFactoryTest2';
76
77		$factory = $this->getUserFactory();
78		$user1 = $factory->newFromName( $name );
79		$user1->addToDatabase();
80
81		$actorId = $user1->getActorId();
82		$this->assertGreaterThan(
83			0,
84			$actorId,
85			'Sanity check: valid actor id for a user'
86		);
87
88		$user2 = $factory->newFromActorId( $actorId );
89		$this->assertInstanceOf( User::class, $user2 );
90		$this->assertSame( $actorId, $user2->getActorId() );
91	}
92
93	public function testNewFromUserIdentity() {
94		$id = 23560;
95		$name = 'UserFactoryTest3';
96
97		$userIdentity = new UserIdentityValue( $id, $name );
98		$factory = $this->getUserFactory();
99
100		$user1 = $factory->newFromUserIdentity( $userIdentity );
101		$this->assertInstanceOf( User::class, $user1 );
102		$this->assertSame( $id, $user1->getId() );
103		$this->assertSame( $name, $user1->getName() );
104
105		$user2 = $factory->newFromUserIdentity( $user1 );
106		$this->assertInstanceOf( User::class, $user1 );
107		$this->assertSame( $user1, $user2 );
108	}
109
110	public function testNewFromAnyId() {
111		$name = 'UserFactoryTest4';
112
113		$factory = $this->getUserFactory();
114		$user1 = $factory->newFromName( $name );
115		$user1->addToDatabase();
116
117		$id = $user1->getId();
118		$this->assertGreaterThan(
119			0,
120			$id,
121			'Sanity check: valid user'
122		);
123		$actorId = $user1->getActorId();
124		$this->assertGreaterThan(
125			0,
126			$actorId,
127			'Sanity check: valid actor id for a user'
128		);
129
130		$user2 = $factory->newFromAnyId( $id, null, null );
131		$this->assertInstanceOf( User::class, $user2 );
132		$this->assertSame( $id, $user2->getId() );
133
134		$user3 = $factory->newFromAnyId( null, $name, null );
135		$this->assertInstanceOf( User::class, $user3 );
136		$this->assertSame( $name, $user3->getName() );
137
138		$user4 = $factory->newFromAnyId( null, null, $actorId );
139		$this->assertInstanceOf( User::class, $user4 );
140		$this->assertSame( $actorId, $user4->getActorId() );
141	}
142
143	public function testNewFromConfirmationCode() {
144		$fakeCode = 'NotARealConfirmationCode';
145
146		$factory = $this->getUserFactory();
147
148		$user1 = $factory->newFromConfirmationCode( $fakeCode );
149		$this->assertNull(
150			$user1,
151			'Invalid confirmation codes result in null users when reading from replicas'
152		);
153
154		$user2 = $factory->newFromConfirmationCode( $fakeCode, UserFactory::READ_LATEST );
155		$this->assertNull(
156			$user2,
157			'Invalid confirmation codes result in null users when reading from master'
158		);
159	}
160
161	// Copied from UserTest
162	public function testNewFromRow() {
163		// TODO: Create real tests here for loadFromRow
164		$row = (object)[];
165		$user = $this->getUserFactory()->newFromRow( $row );
166		$this->assertInstanceOf( User::class, $user, 'newFromRow returns a user object' );
167	}
168
169	public function testNewFromRow_bad() {
170		$this->expectException( InvalidArgumentException::class );
171		$this->expectExceptionMessage( '$row must be an object' );
172		$this->getUserFactory()->newFromRow( [] );
173	}
174
175	/**
176	 * @covers \MediaWiki\User\UserFactory::newFromAuthority
177	 */
178	public function testNewFromAuthority() {
179		$authority = new UltimateAuthority( new UserIdentityValue( 42, 'Test' ) );
180		$user = $this->getUserFactory()->newFromAuthority( $authority );
181		$this->assertSame( 42, $user->getId() );
182		$this->assertSame( 'Test', $user->getName() );
183	}
184
185}
186