Passed
Push — dark-mode-theme-fix ( 5ad7e4...3e6f85 )
by Simon
12:56 queued 09:00
created

MediaWikiHelper::getHtmlForWikiText()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 15
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 10
c 0
b 0
f 0
dl 0
loc 15
ccs 0
cts 13
cp 0
rs 9.9332
cc 1
nc 1
nop 1
crap 2
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
        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
        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
        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
        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
        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
    /**
261
     * Gets the HTML for the provided wiki-markup
262
     *
263
     * @param string $wikiText
264
     *
265
     * @return string
266
     */
267
    public function getHtmlForWikiText($wikiText)
268
    {
269
        $parameters = array(
270
            'action'             => 'parse',
271
            'pst'                => true,
272
            'contentmodel'       => 'wikitext',
273
            'disablelimitreport' => true,
274
            'disabletoc'         => true,
275
            'disableeditsection' => true,
276
            'text'               => $wikiText,
277
        );
278
279
        $apiResult = $this->mediaWikiClient->doApiCall($parameters, 'GET');
280
281
        return $apiResult->parse->text->{'*'};
282
    }
283
}
284