Failed Conditions
Push — newinternal ( b66232...216d62 )
by Simon
16:33 queued 06:35
created

MediaWikiHelper   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 244
Duplicated Lines 7.79 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
dl 19
loc 244
rs 10
c 0
b 0
f 0
wmc 27
lcom 1
cbo 2

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
B createAccount() 6 58 7
B addTalkPageMessage() 10 52 7
C getCreationFieldData() 3 69 11
A checkAccountExists() 0 15 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
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)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
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)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
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)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
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)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
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