Passed
Push — search ( bdb480...5e7f6e )
by Simon
17:14 queued 07:17
created

PageJobQueue::prepareMaps()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 16
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 12
dl 0
loc 16
ccs 0
cts 0
cp 0
rs 9.8666
c 2
b 0
f 0
cc 1
nc 1
nop 0
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\Pages;
10
11
use Waca\Background\Task\BotCreationTask;
12
use Waca\Background\Task\UserCreationTask;
13
use Waca\DataObjects\EmailTemplate;
14
use Waca\DataObjects\JobQueue;
15
use Waca\DataObjects\Log;
16
use Waca\DataObjects\Request;
17
use Waca\DataObjects\User;
18
use Waca\Exceptions\ApplicationLogicException;
19
use Waca\Helpers\Logger;
20
use Waca\Helpers\LogHelper;
21
use Waca\Helpers\SearchHelpers\JobQueueSearchHelper;
22
use Waca\Helpers\SearchHelpers\LogSearchHelper;
23
use Waca\Helpers\SearchHelpers\RequestSearchHelper;
24
use Waca\Helpers\SearchHelpers\UserSearchHelper;
25
use Waca\RequestStatus;
26
use Waca\Tasks\PagedInternalPageBase;
27
use Waca\WebRequest;
28
29
class PageJobQueue extends PagedInternalPageBase
30
{
31
    /**
32
     * Main function for this page, when no specific actions are called.
33
     * @return void
34
     */
35
    protected function main()
36
    {
37
        $this->setHtmlTitle('Job Queue Management');
38
39
        $this->prepareMaps();
40
41
        $database = $this->getDatabase();
42
43
        /** @var JobQueue[] $jobList */
44
        $jobList = JobQueueSearchHelper::get($database)
45
            ->statusIn(array('queued', 'ready', 'waiting', 'running', 'failed'))
46
            ->notAcknowledged()
47
            ->fetch();
48
49
        $userIds = array();
50
        $requestIds = array();
51
52
        foreach ($jobList as $job) {
53
            $userIds[] = $job->getTriggerUserId();
54
            $requestIds[] = $job->getRequest();
55
56
            $job->setDatabase($database);
57
        }
58
59
        $this->assign('canSeeAll', $this->barrierTest('all', User::getCurrent($database)));
60
61
        $this->assign('users', UserSearchHelper::get($database)->inIds($userIds)->fetchMap('username'));
62
        $this->assign('requests', RequestSearchHelper::get($database)->inIds($requestIds)->fetchMap('name'));
63
64
        $this->assign('joblist', $jobList);
65
        $this->setTemplate('jobqueue/main.tpl');
66
    }
67
68
    protected function all()
69
    {
70
        $this->setHtmlTitle('All Jobs');
71
72
        $this->prepareMaps();
73
74
        $database = $this->getDatabase();
75
76
        $searchHelper = JobQueueSearchHelper::get($database);
77
        $this->setSearchHelper($searchHelper);
78
        $this->setupLimits();
79
80
        $filterUser = WebRequest::getString('filterUser');
81
        $filterTask = WebRequest::getString('filterTask');
82
        $filterStatus = WebRequest::getString('filterStatus');
83
        $filterRequest = WebRequest::getString('filterRequest');
84
        $order = WebRequest::getString('order');
85
86
        if ($filterUser !== null) {
87
            $searchHelper->byUser(User::getByUsername($filterUser, $database)->getId());
88
        }
89
90
        if ($filterTask !== null) {
91
            $searchHelper->byTask($filterTask);
92
        }
93
94
        if ($filterStatus !== null) {
95
            $searchHelper->byStatus($filterStatus);
96
        }
97
98
        if ($filterRequest !== null) {
99
            $searchHelper->byRequest($filterRequest);
0 ignored issues
show
Bug introduced by
$filterRequest of type string is incompatible with the type integer expected by parameter $request of Waca\Helpers\SearchHelpe...archHelper::byRequest(). ( Ignorable by Annotation )

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

99
            $searchHelper->byRequest(/** @scrutinizer ignore-type */ $filterRequest);
Loading history...
100
        }
101
        
102
        if ($order === null) {
103
            $searchHelper->newestFirst();
104
        }
105
106
        /** @var JobQueue[] $jobList */
107
        $jobList = $searchHelper->getRecordCount($count)->fetch();
108
109
        $this->setupPageData($count, array(
110
            'filterUser' => $filterUser,
111
            'filterTask' => $filterTask,
112
            'filterStatus' => $filterStatus,
113
            'filterRequest' => $filterRequest,
114
            'order' => $order,
115
        ));
116
117
        $userIds = array();
118
        $requestIds = array();
119
120
        foreach ($jobList as $job) {
121
            $userIds[] = $job->getTriggerUserId();
122
            $requestIds[] = $job->getRequest();
123
124
            $job->setDatabase($database);
125
        }
126
127
        $this->getTypeAheadHelper()->defineTypeAheadSource('username-typeahead', function() use ($database) {
128
            return UserSearchHelper::get($database)->fetchColumn('username');
129
        });
130
131
        $this->assign('users', UserSearchHelper::get($database)->inIds($userIds)->fetchMap('username'));
132
        $this->assign('requests', RequestSearchHelper::get($database)->inIds($requestIds)->fetchMap('name'));
133
134
        $this->assign('joblist', $jobList);
135
136
        $this->addJs("/api.php?action=users&all=true&targetVariable=typeaheaddata");
137
138
        $this->setTemplate('jobqueue/all.tpl');
139
    }
140
141
    protected function view()
142
    {
143
        $jobId = WebRequest::getInt('id');
144
        $database = $this->getDatabase();
145
146
        if ($jobId === null) {
147
            throw new ApplicationLogicException('No job specified');
148
        }
149
150
        /** @var JobQueue $job */
151
        $job = JobQueue::getById($jobId, $database);
152
153
        if ($job === false) {
0 ignored issues
show
introduced by
The condition $job === false is always false.
Loading history...
154
            throw new ApplicationLogicException('Could not find requested job');
155
        }
156
157
        $this->prepareMaps();
158
159
        $this->assign('user', User::getById($job->getTriggerUserId(), $database));
160
        $this->assign('request', Request::getById($job->getRequest(), $database));
161
        $this->assign('emailTemplate', EmailTemplate::getById($job->getEmailTemplate(), $database));
162
        $this->assign('parent', JobQueue::getById($job->getParent(), $database));
163
164
        /** @var Log[] $logs */
165
        $logs = LogSearchHelper::get($database)->byObjectType('JobQueue')
166
            ->byObjectId($job->getId())->getRecordCount($logCount)->fetch();
167
        if ($logCount === 0) {
168
            $this->assign('log', array());
169
        }
170
        else {
171
            list($users, $logData) = LogHelper::prepareLogsForTemplate($logs, $database, $this->getSiteConfiguration());
172
173
            $this->assign("log", $logData);
174
            $this->assign("users", $users);
175
        }
176
177
        $this->assignCSRFToken();
178
179
        $this->assign('job', $job);
180
181
        $this->assign('canAcknowledge', $this->barrierTest('acknowledge', User::getCurrent($database)));
182
        $this->assign('canRequeue', $this->barrierTest('requeue', User::getCurrent($database)));
183
        $this->assign('canCancel', $this->barrierTest('cancel', User::getCurrent($database)));
184
185
        if ($job->getTask() === UserCreationTask::class || $job->getTask() === BotCreationTask::class) {
186
            if ($job->getEmailTemplate() === null) {
0 ignored issues
show
introduced by
The condition $job->getEmailTemplate() === null is always false.
Loading history...
187
                $params = json_decode($job->getParameters());
188
189
                if (isset($params->emailText)) {
190
                    $this->assign("creationEmailText", $params->emailText);
191
                }
192
            }
193
        }
194
195
        $this->setHtmlTitle('Job #{$job->getId()|escape}');
196
        $this->setTemplate('jobqueue/view.tpl');
197
    }
198
199
    protected function acknowledge()
200
    {
201
        if (!WebRequest::wasPosted()) {
202
            throw new ApplicationLogicException('This page does not support GET methods.');
203
        }
204
205
        $this->validateCSRFToken();
206
207
        $jobId = WebRequest::postInt('job');
208
        $database = $this->getDatabase();
209
210
        if ($jobId === null) {
211
            throw new ApplicationLogicException('No job specified');
212
        }
213
214
        /** @var JobQueue $job */
215
        $job = JobQueue::getById($jobId, $database);
216
217
        if ($job === false) {
0 ignored issues
show
introduced by
The condition $job === false is always false.
Loading history...
218
            throw new ApplicationLogicException('Could not find requested job');
219
        }
220
221
        $job->setUpdateVersion(WebRequest::postInt('updateVersion'));
222
        $job->setAcknowledged(true);
0 ignored issues
show
Bug introduced by
true of type true is incompatible with the type integer expected by parameter $acknowledged of Waca\DataObjects\JobQueue::setAcknowledged(). ( Ignorable by Annotation )

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

222
        $job->setAcknowledged(/** @scrutinizer ignore-type */ true);
Loading history...
223
        $job->save();
224
225
        Logger::backgroundJobAcknowledged($database, $job);
226
227
        $this->redirect('jobQueue', 'view', array('id' => $jobId));
228
    }
229
230
    protected function cancel()
231
    {
232
        if (!WebRequest::wasPosted()) {
233
            throw new ApplicationLogicException('This page does not support GET methods.');
234
        }
235
236
        $this->validateCSRFToken();
237
238
        $jobId = WebRequest::postInt('job');
239
        $database = $this->getDatabase();
240
241
        if ($jobId === null) {
242
            throw new ApplicationLogicException('No job specified');
243
        }
244
245
        /** @var JobQueue $job */
246
        $job = JobQueue::getById($jobId, $database);
247
248
        if ($job === false) {
0 ignored issues
show
introduced by
The condition $job === false is always false.
Loading history...
249
            throw new ApplicationLogicException('Could not find requested job');
250
        }
251
252
        if ($job->getStatus() !== JobQueue::STATUS_READY
253
            && $job->getStatus() !== JobQueue::STATUS_QUEUED
254
            && $job->getStatus() === JobQueue::STATUS_WAITING) {
255
            throw new ApplicationLogicException('Cannot cancel job not queued for execution');
256
        }
257
258
        $job->setUpdateVersion(WebRequest::postInt('updateVersion'));
259
        $job->setStatus(JobQueue::STATUS_CANCELLED);
260
        $job->setError("Manually cancelled");
261
        $job->setAcknowledged(null);
262
        $job->save();
263
264
        Logger::backgroundJobCancelled($this->getDatabase(), $job);
265
266
        $this->redirect('jobQueue', 'view', array('id' => $jobId));
267
    }
268
269
    protected function requeue()
270
    {
271
        if (!WebRequest::wasPosted()) {
272
            throw new ApplicationLogicException('This page does not support GET methods.');
273
        }
274
275
        $this->validateCSRFToken();
276
277
        $jobId = WebRequest::postInt('job');
278
        $database = $this->getDatabase();
279
280
        if ($jobId === null) {
281
            throw new ApplicationLogicException('No job specified');
282
        }
283
284
        /** @var JobQueue|false $job */
285
        $job = JobQueue::getById($jobId, $database);
286
287
        if ($job === false) {
0 ignored issues
show
introduced by
The condition $job === false is always false.
Loading history...
288
            throw new ApplicationLogicException('Could not find requested job');
289
        }
290
291
        $job->setStatus(JobQueue::STATUS_QUEUED);
292
        $job->setUpdateVersion(WebRequest::postInt('updateVersion'));
293
        $job->setAcknowledged(null);
294
        $job->setError(null);
295
        $job->save();
296
297
        /** @var Request $request */
298
        $request = Request::getById($job->getRequest(), $database);
299
        $request->setStatus(RequestStatus::JOBQUEUE);
300
        $request->save();
301
302
        Logger::enqueuedJobQueue($database, $request);
303
        Logger::backgroundJobRequeued($database, $job);
304
305
        $this->redirect('jobQueue', 'view', array('id' => $jobId));
306
    }
307
308
    protected function prepareMaps()
309
    {
310
        $taskNameMap = JobQueue::getTaskDescriptions();
311
312
        $statusDecriptionMap = array(
313
            JobQueue::STATUS_CANCELLED => 'The job was cancelled',
314
            JobQueue::STATUS_COMPLETE  => 'The job completed successfully',
315
            JobQueue::STATUS_FAILED    => 'The job encountered an error',
316
            JobQueue::STATUS_QUEUED    => 'The job is in the queue',
317
            JobQueue::STATUS_READY     => 'The job is ready to be picked up by the next job runner execution',
318
            JobQueue::STATUS_RUNNING   => 'The job is being run right now by the job runner',
319
            JobQueue::STATUS_WAITING   => 'The job has been picked up by a job runner',
320
            JobQueue::STATUS_HELD      => 'The job has manually held from processing',
321
        );
322
        $this->assign('taskNameMap', $taskNameMap);
323
        $this->assign('statusDescriptionMap', $statusDecriptionMap);
324
    }
325
}
326