Failed Conditions
Push — multiproject/prefs ( 965e5d )
by Simon
08:54
created

includes/Pages/PageViewRequest.php (1 issue)

Labels
Severity
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\Pages;
10
11
use Exception;
12
use DateTime;
13
use Waca\DataObjects\Comment;
14
use Waca\DataObjects\Domain;
15
use Waca\DataObjects\EmailTemplate;
16
use Waca\DataObjects\JobQueue;
17
use Waca\DataObjects\Log;
18
use Waca\DataObjects\Request;
19
use Waca\DataObjects\RequestQueue;
20
use Waca\DataObjects\User;
21
use Waca\Exceptions\ApplicationLogicException;
22
use Waca\Fragments\RequestData;
23
use Waca\Helpers\LogHelper;
24
use Waca\Helpers\OAuthUserHelper;
25
use Waca\Helpers\PreferenceManager;
26
use Waca\Pages\RequestAction\PageManuallyConfirm;
27
use Waca\PdoDatabase;
28
use Waca\Security\RoleConfiguration;
29
use Waca\RequestStatus;
30
use Waca\Tasks\InternalPageBase;
31
use Waca\WebRequest;
32
33
class PageViewRequest extends InternalPageBase
34
{
35
    use RequestData;
36
    const STATUS_SYMBOL_OPEN = '&#927';
37
    const STATUS_SYMBOL_ACCEPTED = '&#x2611';
38
    const STATUS_SYMBOL_REJECTED = '&#x2612';
39
40
    /**
41
     * Main function for this page, when no specific actions are called.
42
     * @throws ApplicationLogicException
43
     */
44
    protected function main()
45
    {
46
        // set up csrf protection
47
        $this->assignCSRFToken();
48
49
        // get some useful objects
50
        $database = $this->getDatabase();
51
        $request = $this->getRequest($database, WebRequest::getInt('id'));
52
        $config = $this->getSiteConfiguration();
53
        $currentUser = User::getCurrent($database);
54
55
        // FIXME: domains!
56
        /** @var Domain $domain */
57
        $domain = Domain::getById(1, $this->getDatabase());
58
        $this->assign('mediawikiScriptPath', $domain->getWikiArticlePath());
59
60
        // Shows a page if the email is not confirmed.
61
        if ($request->getEmailConfirm() !== 'Confirmed') {
62
            // Show a banner if the user can manually confirm the request
63
            $viewConfirm = $this->barrierTest(RoleConfiguration::MAIN, $currentUser, PageManuallyConfirm::class);
64
65
            // If the request is purged, there's nothing to confirm!
66
            if ($request->getEmail() === $this->getSiteConfiguration()->getDataClearEmail()) {
67
                $viewConfirm = false;
68
            }
69
70
            // Render
71
            $this->setTemplate("view-request/not-confirmed.tpl");
72
            $this->assign("requestId", $request->getId());
73
            $this->assign("requestVersion", $request->getUpdateVersion());
74
            $this->assign('canViewConfirmButton', $viewConfirm);
75
76
            // Make sure to return, to prevent the leaking of other information.
77
            return;
78
        }
79
80
        $this->setupBasicData($request, $config);
81
82
        $this->setupUsernameData($request);
83
84
        $this->setupTitle($request);
85
86
        $this->setupReservationDetails($request->getReserved(), $database, $currentUser);
87
        $this->setupGeneralData($database);
88
89
        $this->assign('requestDataCleared', false);
90
        if ($request->getEmail() === $this->getSiteConfiguration()->getDataClearEmail()) {
91
            $this->assign('requestDataCleared', true);
92
        }
93
94
        $allowedPrivateData = $this->isAllowedPrivateData($request, $currentUser);
95
96
        $this->setupCreationTypes($currentUser);
97
98
        $this->setupLogData($request, $database);
99
100
        $this->addJs("/api.php?action=templates&targetVariable=templateconfirms");
101
102
        $this->assign('showRevealLink', false);
103
        if ($request->getReserved() === $currentUser->getId() ||
104
            $this->barrierTest('alwaysSeeHash', $currentUser, 'RequestData')
105
        ) {
106
            $this->assign('showRevealLink', true);
107
            $this->assign('revealHash', $request->getRevealHash());
108
        }
109
110
        $this->assign('canSeeRelatedRequests', false);
111
        if ($allowedPrivateData || $this->barrierTest('seeRelatedRequests', $currentUser, 'RequestData')) {
112
            $this->setupRelatedRequests($request, $config, $database);
113
        }
114
115
        $this->assign('canCreateLocalAccount', $this->barrierTest('createLocalAccount', $currentUser, 'RequestData'));
116
            
117
        $closureDate = $request->getClosureDate();
118
        $date = new DateTime();
119
        $date->modify("-7 days");
120
        if ($request->getStatus() == "Closed" && $closureDate < $date) {
121
                $this->assign('isOldRequest', true);
122
        }
123
        $this->assign('canResetOldRequest', $this->barrierTest('reopenOldRequest', $currentUser, 'RequestData'));
124
        $this->assign('canResetPurgedRequest', $this->barrierTest('reopenClearedRequest', $currentUser, 'RequestData'));
125
126
        $this->assign('requestEmailSent', $request->getEmailSent());
127
128
        if ($allowedPrivateData) {
129
            $this->setTemplate('view-request/main-with-data.tpl');
130
            $this->setupPrivateData($request, $config);
131
            $this->assign('canSetBan', $this->barrierTest('set', $currentUser, PageBan::class));
132
            $this->assign('canSeeCheckuserData', $this->barrierTest('seeUserAgentData', $currentUser, 'RequestData'));
133
134
            if ($this->barrierTest('seeUserAgentData', $currentUser, 'RequestData')) {
135
                $this->setTemplate('view-request/main-with-checkuser-data.tpl');
136
                $this->setupCheckUserData($request);
137
            }
138
        }
139
        else {
140
            $this->setTemplate('view-request/main.tpl');
141
        }
142
    }
143
144
    /**
145
     * @param Request $request
146
     */
147
    protected function setupTitle(Request $request)
148
    {
149
        $statusSymbol = self::STATUS_SYMBOL_OPEN;
150
        if ($request->getStatus() === RequestStatus::CLOSED) {
151
            if ($request->getWasCreated()) {
152
                $statusSymbol = self::STATUS_SYMBOL_ACCEPTED;
153
            }
154
            else {
155
                $statusSymbol = self::STATUS_SYMBOL_REJECTED;
156
            }
157
        }
158
159
        $this->setHtmlTitle($statusSymbol . ' #' . $request->getId());
160
    }
161
162
    /**
163
     * Sets up data unrelated to the request, such as the email template information
164
     *
165
     * @param PdoDatabase $database
166
     */
167
    protected function setupGeneralData(PdoDatabase $database)
168
    {
169
        $this->assign('createAccountReason', 'Requested account at [[WP:ACC]], request #');
170
171
        // FIXME: domains
172
        /** @var Domain $domain */
173
        $domain = Domain::getById(1, $database);
174
        $this->assign('defaultRequestState', RequestQueue::getDefaultQueue($database, 1)->getApiName());
175
        $this->assign('activeRequestQueues', RequestQueue::getEnabledQueues($database));
176
177
        /** @var EmailTemplate $createdTemplate */
178
        $createdTemplate = EmailTemplate::getById($domain->getDefaultClose(), $database);
179
180
        $this->assign('createdHasJsQuestion', $createdTemplate->getJsquestion() != '');
181
        $this->assign('createdId', $createdTemplate->getId());
182
        $this->assign('createdName', $createdTemplate->getName());
183
184
        $preferenceManager = PreferenceManager::getForCurrent($database);
185
        $skipJsAborts = $preferenceManager->getPreference(PreferenceManager::PREF_SKIP_JS_ABORT);
186
        $preferredCreationMode = (int)$preferenceManager->getPreference(PreferenceManager::PREF_CREATION_MODE);
187
        $this->assign('skipJsAborts', $skipJsAborts);
188
        $this->assign('preferredCreationMode', $preferredCreationMode);
189
190
        $createReasons = EmailTemplate::getActiveNonpreloadTemplates(EmailTemplate::ACTION_CREATED, $database, $domain->getDefaultClose());
191
        $this->assign("createReasons", $createReasons);
192
        $declineReasons = EmailTemplate::getActiveNonpreloadTemplates(EmailTemplate::ACTION_NOT_CREATED, $database);
193
        $this->assign("declineReasons", $declineReasons);
194
195
        $allCreateReasons = EmailTemplate::getAllActiveTemplates(EmailTemplate::ACTION_CREATED, $database);
196
        $this->assign("allCreateReasons", $allCreateReasons);
197
        $allDeclineReasons = EmailTemplate::getAllActiveTemplates(EmailTemplate::ACTION_NOT_CREATED, $database);
198
        $this->assign("allDeclineReasons", $allDeclineReasons);
199
        $allOtherReasons = EmailTemplate::getAllActiveTemplates(false, $database);
200
        $this->assign("allOtherReasons", $allOtherReasons);
201
    }
202
203
    private function setupLogData(Request $request, PdoDatabase $database)
204
    {
205
        $currentUser = User::getCurrent($database);
206
207
        $logs = LogHelper::getRequestLogsWithComments($request->getId(), $database, $this->getSecurityManager());
208
        $requestLogs = array();
209
210
        /** @var User[] $nameCache */
211
        $nameCache = array();
212
213
        $editableComments = $this->barrierTest('editOthers', $currentUser, PageEditComment::class);
214
215
        $canFlag = $this->barrierTest(RoleConfiguration::MAIN, $currentUser, PageFlagComment::class);
216
        $canUnflag = $this->barrierTest('unflag', $currentUser, PageFlagComment::class);
217
218
        /** @var Log|Comment $entry */
219
        foreach ($logs as $entry) {
220
            // both log and comment have a 'user' field
221
            if (!array_key_exists($entry->getUser(), $nameCache)) {
0 ignored issues
show
The method getUser() does not exist on Waca\DataObject. It seems like you code against a sub-type of Waca\DataObject such as Waca\DataObjects\Log or Waca\DataObjects\Ban or Waca\DataObjects\UserDomain or Waca\DataObjects\UserRole or Waca\DataObjects\Comment or Waca\DataObjects\UserPreference. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

221
            if (!array_key_exists($entry->/** @scrutinizer ignore-call */ getUser(), $nameCache)) {
Loading history...
222
                $entryUser = User::getById($entry->getUser(), $database);
223
                $nameCache[$entry->getUser()] = $entryUser;
224
            }
225
226
            if ($entry instanceof Comment) {
227
                $requestLogs[] = array(
228
                    'type'          => 'comment',
229
                    'security'      => $entry->getVisibility(),
230
                    'user'          => $entry->getVisibility() == 'requester' ? $request->getName() : $nameCache[$entry->getUser()]->getUsername(),
231
                    'userid'        => $entry->getUser() == -1 ? null : $entry->getUser(),
232
                    'entry'         => null,
233
                    'time'          => $entry->getTime(),
234
                    'canedit'       => ($editableComments || $entry->getUser() == $currentUser->getId()),
235
                    'id'            => $entry->getId(),
236
                    'comment'       => $entry->getComment(),
237
                    'flagged'       => $entry->getFlagged(),
238
                    'canflag'       => $canFlag && (!$entry->getFlagged() || ($entry->getFlagged() && $canUnflag)),
239
                    'updateversion' => $entry->getUpdateVersion(),
240
                    'edited'        => $entry->getEdited()
241
                );
242
            }
243
244
            if ($entry instanceof Log) {
245
                $invalidUserId = $entry->getUser() === -1 || $entry->getUser() === 0;
246
                $entryUser = $invalidUserId ? User::getCommunity() : $nameCache[$entry->getUser()];
247
248
                $entryComment = $entry->getComment();
249
250
                if ($entry->getAction() === 'JobIssueRequest' || $entry->getAction() === 'JobCompletedRequest') {
251
                    $data = unserialize($entry->getComment());
252
                    /** @var JobQueue $job */
253
                    $job = JobQueue::getById($data['job'], $database);
254
                    $requestLogs[] = array(
255
                        'type'     => 'joblog',
256
                        'security' => 'user',
257
                        'userid'   => $entry->getUser() == -1 ? null : $entry->getUser(),
258
                        'user'     => $entryUser->getUsername(),
259
                        'entry'    => LogHelper::getLogDescription($entry),
260
                        'time'     => $entry->getTimestamp(),
261
                        'canedit'  => false,
262
                        'id'       => $entry->getId(),
263
                        'jobId'    => $job->getId(),
264
                        'jobDesc'  => JobQueue::getTaskDescriptions()[$job->getTask()],
265
                    );
266
                }
267
                else {
268
                    $requestLogs[] = array(
269
                        'type'     => 'log',
270
                        'security' => 'user',
271
                        'userid'   => $entry->getUser() == -1 ? null : $entry->getUser(),
272
                        'user'     => $entryUser->getUsername(),
273
                        'entry'    => LogHelper::getLogDescription($entry),
274
                        'time'     => $entry->getTimestamp(),
275
                        'canedit'  => false,
276
                        'id'       => $entry->getId(),
277
                        'comment'  => $entryComment,
278
                    );
279
                }
280
            }
281
        }
282
283
        $this->addJs("/api.php?action=users&targetVariable=typeaheaddata");
284
285
        $this->assign("requestLogs", $requestLogs);
286
    }
287
288
    /**
289
     * @param Request $request
290
     */
291
    protected function setupUsernameData(Request $request)
292
    {
293
        $blacklistData = $this->getBlacklistHelper()->isBlacklisted($request->getName());
294
295
        $this->assign('requestIsBlacklisted', $blacklistData !== false);
296
        $this->assign('requestBlacklist', $blacklistData);
297
298
        try {
299
            $spoofs = $this->getAntiSpoofProvider()->getSpoofs($request->getName());
300
        }
301
        catch (Exception $ex) {
302
            $spoofs = $ex->getMessage();
303
        }
304
305
        $this->assign("spoofs", $spoofs);
306
    }
307
308
    private function setupCreationTypes(User $user)
309
    {
310
        $this->assign('allowWelcomeSkip', false);
311
        $this->assign('forceWelcomeSkip', false);
312
313
        $database = $this->getDatabase();
314
        $preferenceManager = PreferenceManager::getForCurrent($database);
315
316
        $oauth = new OAuthUserHelper($user, $database, $this->getOAuthProtocolHelper(), $this->getSiteConfiguration());
317
318
        $welcomeTemplate = $preferenceManager->getPreference(PreferenceManager::PREF_WELCOMETEMPLATE);
319
320
        if ($welcomeTemplate != null) {
321
            $this->assign('allowWelcomeSkip', true);
322
323
            if (!$oauth->canWelcome()) {
324
                $this->assign('forceWelcomeSkip', true);
325
            }
326
        }
327
328
        // test credentials
329
        $canManualCreate = $this->barrierTest(PreferenceManager::CREATION_MANUAL, $user, 'RequestCreation');
330
        $canOauthCreate = $this->barrierTest(PreferenceManager::CREATION_OAUTH, $user, 'RequestCreation');
331
        $canBotCreate = $this->barrierTest(PreferenceManager::CREATION_BOT, $user, 'RequestCreation');
332
333
        $this->assign('canManualCreate', $canManualCreate);
334
        $this->assign('canOauthCreate', $canOauthCreate);
335
        $this->assign('canBotCreate', $canBotCreate);
336
337
        // show/hide the type radio buttons
338
        $creationHasChoice = count(array_filter([$canManualCreate, $canOauthCreate, $canBotCreate])) > 1;
339
340
        $creationModePreference = $preferenceManager->getPreference(PreferenceManager::PREF_CREATION_MODE);
341
        if (!$this->barrierTest($creationModePreference, $user, 'RequestCreation')) {
342
            // user is not allowed to use their default. Force a choice.
343
            $creationHasChoice = true;
344
        }
345
346
        $this->assign('creationHasChoice', $creationHasChoice);
347
348
        // determine problems in creation types
349
        $this->assign('botProblem', false);
350
        if ($canBotCreate && $this->getSiteConfiguration()->getCreationBotPassword() === null) {
351
            $this->assign('botProblem', true);
352
        }
353
354
        $this->assign('oauthProblem', false);
355
        if ($canOauthCreate && !$oauth->canCreateAccount()) {
356
            $this->assign('oauthProblem', true);
357
        }
358
    }
359
}
360