1
|
|
|
<?php |
2
|
|
|
/****************************************************************************** |
3
|
|
|
* Wikipedia Account Creation Assistance tool * |
4
|
|
|
* * |
5
|
|
|
* All code in this file is released into the public domain by the ACC * |
6
|
|
|
* Development Team. Please see team.json for a list of contributors. * |
7
|
|
|
******************************************************************************/ |
8
|
|
|
|
9
|
|
|
namespace Waca\Helpers; |
10
|
|
|
|
11
|
|
|
use Exception; |
12
|
|
|
use Waca\Exceptions\MediaWikiApiException; |
13
|
|
|
use Waca\Helpers\Interfaces\IMediaWikiClient; |
14
|
|
|
use Waca\SiteConfiguration; |
15
|
|
|
|
16
|
|
|
class MediaWikiHelper |
17
|
|
|
{ |
18
|
|
|
/** |
19
|
|
|
* @var IMediaWikiClient |
20
|
|
|
*/ |
21
|
|
|
private $mediaWikiClient; |
22
|
|
|
/** |
23
|
|
|
* @var SiteConfiguration |
24
|
|
|
*/ |
25
|
|
|
private $siteConfiguration; |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* MediaWikiHelper constructor. |
29
|
|
|
* |
30
|
|
|
* @param IMediaWikiClient $mediaWikiClient |
31
|
|
|
* @param SiteConfiguration $siteConfiguration |
32
|
|
|
*/ |
33
|
|
|
public function __construct(IMediaWikiClient $mediaWikiClient, SiteConfiguration $siteConfiguration) |
34
|
|
|
{ |
35
|
|
|
$this->mediaWikiClient = $mediaWikiClient; |
36
|
|
|
$this->siteConfiguration = $siteConfiguration; |
37
|
|
|
} |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* @todo handle override antispoof and titleblacklist issues |
41
|
|
|
* |
42
|
|
|
* @param string $username |
43
|
|
|
* @param string $emailAddress |
44
|
|
|
* @param string $reason |
45
|
|
|
* |
46
|
|
|
* @throws Exception |
47
|
|
|
* @throws MediaWikiApiException |
48
|
|
|
*/ |
49
|
|
|
public function createAccount($username, $emailAddress, $reason) |
50
|
|
|
{ |
51
|
|
|
// get token |
52
|
|
|
$tokenParams = array( |
53
|
|
|
'action' => 'query', |
54
|
|
|
'meta' => 'tokens', |
55
|
|
|
'type' => 'createaccount', |
56
|
|
|
); |
57
|
|
|
|
58
|
|
|
$response = $this->mediaWikiClient->doApiCall($tokenParams, 'POST'); |
59
|
|
|
|
60
|
|
View Code Duplication |
if (isset($response->error)) { |
|
|
|
|
61
|
|
|
throw new MediaWikiApiException($response->error->code . ': ' . $response->error->info); |
62
|
|
|
} |
63
|
|
|
|
64
|
|
|
$token = $response->query->tokens->createaccounttoken; |
65
|
|
|
|
66
|
|
|
$callback = $this->siteConfiguration->getBaseUrl() . '/internal.php/oauth/createCallback'; |
67
|
|
|
|
68
|
|
|
$checkboxFields = array(); |
69
|
|
|
$requiredFields = array(); |
70
|
|
|
$this->getCreationFieldData($requiredFields, $checkboxFields); |
71
|
|
|
|
72
|
|
|
$apiCallData = array( |
73
|
|
|
'action' => 'createaccount', |
74
|
|
|
'createreturnurl' => $callback, |
75
|
|
|
'createtoken' => $token, |
76
|
|
|
'createmessageformat' => 'html', |
77
|
|
|
); |
78
|
|
|
|
79
|
|
|
$createParams = array_fill_keys($requiredFields, '') + $apiCallData; |
80
|
|
|
|
81
|
|
|
$createParams['username'] = $username; |
82
|
|
|
$createParams['mailpassword'] = true; |
83
|
|
|
$createParams['email'] = $emailAddress; |
84
|
|
|
$createParams['reason'] = $reason; |
85
|
|
|
|
86
|
|
|
$createResponse = $this->mediaWikiClient->doApiCall($createParams, 'POST'); |
87
|
|
|
|
88
|
|
View Code Duplication |
if (isset($createResponse->error)) { |
|
|
|
|
89
|
|
|
throw new MediaWikiApiException($response->error->code . ': ' . $response->error->info); |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
if (!isset($createResponse->createaccount) || !isset($createResponse->createaccount->status)) { |
93
|
|
|
throw new MediaWikiApiException('Unknown error creating account'); |
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
if ($createResponse->createaccount->status === 'FAIL') { |
97
|
|
|
throw new MediaWikiApiException($createResponse->createaccount->message); |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
if ($createResponse->createaccount->status === 'PASS') { |
101
|
|
|
// success! |
102
|
|
|
return; |
103
|
|
|
} |
104
|
|
|
|
105
|
|
|
throw new Exception('API result reported status of ' . $createResponse->createaccount->status); |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
/** |
109
|
|
|
* @param string $username |
110
|
|
|
* @param string $title |
111
|
|
|
* @param $summary |
112
|
|
|
* @param string $message |
113
|
|
|
* @param bool $createOnly |
114
|
|
|
* |
115
|
|
|
* @throws MediaWikiApiException |
116
|
|
|
*/ |
117
|
|
|
public function addTalkPageMessage($username, $title, $summary, $message, $createOnly = true) |
118
|
|
|
{ |
119
|
|
|
// get token |
120
|
|
|
$tokenParams = array( |
121
|
|
|
'action' => 'query', |
122
|
|
|
'meta' => 'tokens', |
123
|
|
|
'type' => 'csrf', |
124
|
|
|
); |
125
|
|
|
|
126
|
|
|
$response = $this->mediaWikiClient->doApiCall($tokenParams, 'POST'); |
127
|
|
|
|
128
|
|
View Code Duplication |
if (isset($response->error)) { |
|
|
|
|
129
|
|
|
throw new MediaWikiApiException($response->error->code . ': ' . $response->error->info); |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
$token = $response->query->tokens->csrftoken; |
133
|
|
|
|
134
|
|
|
if ($token === null) { |
135
|
|
|
throw new MediaWikiApiException('Edit token could not be acquired'); |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
$editParameters = array( |
139
|
|
|
'action' => 'edit', |
140
|
|
|
'title' => 'User talk:' . $username, |
141
|
|
|
'section' => 'new', |
142
|
|
|
'sectiontitle' => $title, |
143
|
|
|
'summary' => $summary, |
144
|
|
|
'text' => $message, |
145
|
|
|
'token' => $token, |
146
|
|
|
); |
147
|
|
|
|
148
|
|
|
if ($createOnly) { |
149
|
|
|
$editParameters['createonly'] = true; |
150
|
|
|
} |
151
|
|
|
|
152
|
|
|
$response = $this->mediaWikiClient->doApiCall($editParameters, 'POST'); |
153
|
|
|
|
154
|
|
View Code Duplication |
if (!isset($response->edit)) { |
|
|
|
|
155
|
|
|
if (isset($response->error)) { |
156
|
|
|
throw new MediaWikiApiException($response->error->code . ': ' . $response->error->info); |
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
throw new MediaWikiApiException('Unknown error encountered during editing.'); |
160
|
|
|
} |
161
|
|
|
|
162
|
|
|
$editResponse = $response->edit; |
163
|
|
|
if ($editResponse->result === "Success") { |
164
|
|
|
return; |
165
|
|
|
} |
166
|
|
|
|
167
|
|
|
throw new MediaWikiApiException('Edit status unsuccessful: ' . $editResponse->result); |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
public function getCreationFieldData(&$requiredFields, &$checkboxFields) |
171
|
|
|
{ |
172
|
|
|
// get token |
173
|
|
|
$params = array( |
174
|
|
|
'action' => 'query', |
175
|
|
|
'meta' => 'authmanagerinfo', |
176
|
|
|
'amirequestsfor' => 'create', |
177
|
|
|
); |
178
|
|
|
|
179
|
|
|
$response = $this->mediaWikiClient->doApiCall($params, 'GET'); |
180
|
|
|
|
181
|
|
View Code Duplication |
if (isset($response->error)) { |
|
|
|
|
182
|
|
|
throw new MediaWikiApiException($response->error->code . ': ' . $response->error->info); |
183
|
|
|
} |
184
|
|
|
|
185
|
|
|
$requests = $response->query->authmanagerinfo->requests; |
186
|
|
|
|
187
|
|
|
// We don't want to deal with these providers ever. |
188
|
|
|
$discardList = array( |
189
|
|
|
// Requires a username and password |
190
|
|
|
'MediaWiki\\Auth\\PasswordAuthenticationRequest', |
191
|
|
|
); |
192
|
|
|
|
193
|
|
|
// We require these providers to function |
194
|
|
|
$requireList = array( |
195
|
|
|
'MediaWiki\\Auth\\TemporaryPasswordAuthenticationRequest', |
196
|
|
|
'MediaWiki\\Auth\\UsernameAuthenticationRequest', |
197
|
|
|
'MediaWiki\\Auth\\UserDataAuthenticationRequest', |
198
|
|
|
'MediaWiki\\Auth\\CreationReasonAuthenticationRequest', |
199
|
|
|
); |
200
|
|
|
|
201
|
|
|
$requiredFields = array(); |
202
|
|
|
// Keep checkbox fields separate, since "required" actually means optional as absent == false. |
203
|
|
|
$checkboxFields = array(); |
204
|
|
|
|
205
|
|
|
foreach ($requests as $req) { |
206
|
|
|
// Immediately discard anything that is on the discard list. |
207
|
|
|
if (in_array($req->id, $discardList)) { |
208
|
|
|
continue; |
209
|
|
|
} |
210
|
|
|
|
211
|
|
|
$required = false; |
212
|
|
|
|
213
|
|
|
if ($req->required === 'primary-required' && !in_array($req->id, $requireList)) { |
214
|
|
|
// Only want one. |
215
|
|
|
continue; |
216
|
|
|
} |
217
|
|
|
|
218
|
|
|
if (in_array($req->id, $requireList)) { |
219
|
|
|
unset($requireList[$req->id]); |
220
|
|
|
$required = true; |
221
|
|
|
} |
222
|
|
|
|
223
|
|
|
if ($req->required === 'required') { |
224
|
|
|
$required = true; |
225
|
|
|
} |
226
|
|
|
|
227
|
|
|
if ($required) { |
228
|
|
|
foreach ($req->fields as $name => $data) { |
229
|
|
|
if ($data->type === 'checkbox') { |
230
|
|
|
$checkboxFields[] = $name; |
231
|
|
|
} |
232
|
|
|
else { |
233
|
|
|
$requiredFields[] = $name; |
234
|
|
|
} |
235
|
|
|
} |
236
|
|
|
} |
237
|
|
|
} |
238
|
|
|
} |
239
|
|
|
|
240
|
|
|
/** |
241
|
|
|
* @param string $username |
242
|
|
|
* @return bool |
243
|
|
|
*/ |
244
|
|
|
public function checkAccountExists($username) { |
245
|
|
|
$parameters = array( |
246
|
|
|
'action' => 'query', |
247
|
|
|
'list' => 'users', |
248
|
|
|
'format' => 'php', |
249
|
|
|
'ususers' => $username, |
250
|
|
|
); |
251
|
|
|
|
252
|
|
|
$apiResult = $this->mediaWikiClient->doApiCall($parameters, 'GET'); |
253
|
|
|
|
254
|
|
|
$entry = $apiResult->query->users[0]; |
255
|
|
|
$exists = !isset($entry->missing); |
256
|
|
|
|
257
|
|
|
return $exists; |
258
|
|
|
} |
259
|
|
|
} |
260
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.