Failed Conditions
Push — rbac ( 1ec5d5 )
by Simon
18:18 queued 05:15
created

LogHelper::prepareLogsForTemplate()   C

Complexity

Conditions 10
Paths 17

Size

Total Lines 71
Code Lines 42

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 110

Importance

Changes 0
Metric Value
cc 10
eloc 42
nc 17
nop 3
dl 0
loc 71
ccs 0
cts 55
cp 0
crap 110
rs 5.9513
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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 PDO;
13
use Waca\DataObject;
14
use Waca\DataObjects\Ban;
15
use Waca\DataObjects\Comment;
16
use Waca\DataObjects\EmailTemplate;
17
use Waca\DataObjects\Log;
18
use Waca\DataObjects\Request;
19
use Waca\DataObjects\User;
20
use Waca\DataObjects\WelcomeTemplate;
21
use Waca\Helpers\SearchHelpers\LogSearchHelper;
22
use Waca\Helpers\SearchHelpers\UserSearchHelper;
23
use Waca\PdoDatabase;
24
use Waca\Security\SecurityManager;
25
use Waca\SiteConfiguration;
26
27
class LogHelper
28
{
29
    /**
30
     * Summary of getRequestLogsWithComments
31
     *
32
     * @param int             $requestId
33
     * @param PdoDatabase     $db
34
     * @param SecurityManager $securityManager
35
     *
36
     * @return \Waca\DataObject[]
37
     */
38
    public static function getRequestLogsWithComments($requestId, PdoDatabase $db, SecurityManager $securityManager)
39
    {
40
        $logs = LogSearchHelper::get($db)->byObjectType('Request')->byObjectId($requestId)->fetch();
41
42
        $currentUser = User::getCurrent($db);
43
        $securityResult = $securityManager->allows('RequestData', 'seeRestrictedComments', $currentUser);
44
        $showAllComments = $securityResult === SecurityManager::ALLOWED;
45
46
        $comments = Comment::getForRequest($requestId, $db, $showAllComments, $currentUser->getId());
47
48
        $items = array_merge($logs, $comments);
49
50
        /**
51
         * @param DataObject $item
52
         *
53
         * @return int
54
         */
55
        $sortKey = function(DataObject $item) {
56
            if ($item instanceof Log) {
57
                return $item->getTimestamp()->getTimestamp();
58
            }
59
60
            if ($item instanceof Comment) {
61
                return $item->getTime()->getTimestamp();
62
            }
63
64
            return 0;
65
        };
66
67
        do {
68
            $flag = false;
69
70
            $loopLimit = (count($items) - 1);
71
            for ($i = 0; $i < $loopLimit; $i++) {
72
                // are these two items out of order?
73
                if ($sortKey($items[$i]) > $sortKey($items[$i + 1])) {
74
                    // swap them
75
                    $swap = $items[$i];
76
                    $items[$i] = $items[$i + 1];
77
                    $items[$i + 1] = $swap;
78
79
                    // set a flag to say we've modified the array this time around
80
                    $flag = true;
81
                }
82
            }
83
        }
84
        while ($flag);
85
86
        return $items;
87
    }
88
89
    /**
90
     * Summary of getLogDescription
91
     *
92
     * @param Log $entry
93
     *
94
     * @return string
95
     */
96
    public static function getLogDescription(Log $entry)
97
    {
98
        $text = "Deferred to ";
99
        if (substr($entry->getAction(), 0, strlen($text)) == $text) {
100
            // Deferred to a different queue
101
            // This is exactly what we want to display.
102
            return $entry->getAction();
103
        }
104
105
        $text = "Closed custom-n";
106
        if ($entry->getAction() == $text) {
107
            // Custom-closed
108
            return "closed (custom reason - account not created)";
109
        }
110
111
        $text = "Closed custom-y";
112
        if ($entry->getAction() == $text) {
113
            // Custom-closed
114
            return "closed (custom reason - account created)";
115
        }
116
117
        $text = "Closed 0";
118
        if ($entry->getAction() == $text) {
119
            // Dropped the request - short-circuit the lookup
120
            return "dropped request";
121
        }
122
123
        $text = "Closed ";
124
        if (substr($entry->getAction(), 0, strlen($text)) == $text) {
125
            // Closed with a reason - do a lookup here.
126
            $id = substr($entry->getAction(), strlen($text));
127
            /** @var EmailTemplate $template */
128
            $template = EmailTemplate::getById((int)$id, $entry->getDatabase());
129
130
            if ($template != false) {
131
                return "closed (" . $template->getName() . ")";
132
            }
133
        }
134
135
        // Fall back to the basic stuff
136
        $lookup = array(
137
            'Reserved'        => 'reserved',
138
            'Email Confirmed' => 'email-confirmed',
139
            'Unreserved'      => 'unreserved',
140
            'Approved'        => 'approved',
141
            'Suspended'       => 'suspended',
142
            'RoleChange'      => 'changed roles',
143
            'Banned'          => 'banned',
144
            'Edited'          => 'edited interface message',
145
            'Declined'        => 'declined',
146
            'EditComment-c'   => 'edited a comment',
147
            'EditComment-r'   => 'edited a comment',
148
            'Unbanned'        => 'unbanned',
149
            'Promoted'        => 'promoted to tool admin',
150
            'BreakReserve'    => 'forcibly broke the reservation',
151
            'Prefchange'      => 'changed user preferences',
152
            'Renamed'         => 'renamed',
153
            'Demoted'         => 'demoted from tool admin',
154
            'ReceiveReserved' => 'received the reservation',
155
            'SendReserved'    => 'sent the reservation',
156
            'EditedEmail'     => 'edited email',
157
            'DeletedTemplate' => 'deleted template',
158
            'EditedTemplate'  => 'edited template',
159
            'CreatedEmail'    => 'created email',
160
            'CreatedTemplate' => 'created template',
161
            'SentMail'        => 'sent an email to the requestor',
162
            'Registered'      => 'registered a tool account',
163
        );
164
165
        if (array_key_exists($entry->getAction(), $lookup)) {
166
            return $lookup[$entry->getAction()];
167
        }
168
169
        // OK, I don't know what this is. Fall back to something sane.
170
        return "performed an unknown action ({$entry->getAction()})";
171
    }
172
173
    /**
174
     * @param PdoDatabase $database
175
     *
176
     * @return array
177
     */
178
    public static function getLogActions(PdoDatabase $database)
179
    {
180
        $lookup = array(
181
            'Reserved'        => 'reserved',
182
            'Email Confirmed' => 'email-confirmed',
183
            'Unreserved'      => 'unreserved',
184
            'Approved'        => 'approved',
185
            'Suspended'       => 'suspended',
186
            'RoleChange'      => 'changed roles',
187
            'Banned'          => 'banned',
188
            'Edited'          => 'edited interface message',
189
            'Declined'        => 'declined',
190
            'EditComment-c'   => 'edited a comment (by comment ID)',
191
            'EditComment-r'   => 'edited a comment (by request)',
192
            'Unbanned'        => 'unbanned',
193
            'Promoted'        => 'promoted to tool admin',
194
            'BreakReserve'    => 'forcibly broke the reservation',
195
            'Prefchange'      => 'changed user preferences',
196
            'Renamed'         => 'renamed',
197
            'Demoted'         => 'demoted from tool admin',
198
            'ReceiveReserved' => 'received the reservation',
199
            'SendReserved'    => 'sent the reservation',
200
            'EditedEmail'     => 'edited email',
201
            'DeletedTemplate' => 'deleted template',
202
            'EditedTemplate'  => 'edited template',
203
            'CreatedEmail'    => 'created email',
204
            'CreatedTemplate' => 'created template',
205
            'SentMail'        => 'sent an email to the requestor',
206
            'Registered'      => 'registered a tool account',
207
            'Closed 0'        => 'dropped request',
208
        );
209
210
        $statement = $database->query(<<<SQL
211
SELECT CONCAT('Closed ', id) AS k, CONCAT('closed (',name,')') AS v
212
FROM emailtemplate;
213
SQL
214
        );
215
        foreach ($statement->fetchAll(PDO::FETCH_ASSOC) as $row) {
216
            $lookup[$row['k']] = $row['v'];
217
        }
218
219
        return $lookup;
220
    }
221
222
    /**
223
     * This returns a HTML
224
     *
225
     * @param string            $objectId
226
     * @param string            $objectType
227
     * @param PdoDatabase       $database
228
     * @param SiteConfiguration $configuration
229
     *
230
     * @return null|string
231
     * @category Security-Critical
232
     */
233
    private static function getObjectDescription(
234
        $objectId,
235
        $objectType,
236
        PdoDatabase $database,
237
        SiteConfiguration $configuration
238
    ) {
239
        if ($objectType == '') {
240
            return null;
241
        }
242
243
        $baseurl = $configuration->getBaseUrl();
244
245
        switch ($objectType) {
246
            case 'Ban':
247
                /** @var Ban $ban */
248
                $ban = Ban::getById($objectId, $database);
249
250
                return 'Ban #' . $objectId . " (" . htmlentities($ban->getTarget()) . ")</a>";
251 View Code Duplication
            case 'EmailTemplate':
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...
252
                /** @var EmailTemplate $emailTemplate */
253
                $emailTemplate = EmailTemplate::getById($objectId, $database);
254
                $name = htmlentities($emailTemplate->getName(), ENT_COMPAT, 'UTF-8');
255
256
                return <<<HTML
257
<a href="{$baseurl}/internal.php/emailManagement/view?id={$objectId}">Email Template #{$objectId} ({$name})</a>
258
HTML;
259
            case 'SiteNotice':
260
                return "<a href=\"{$baseurl}/internal.php/siteNotice\">the site notice</a>";
261 View Code Duplication
            case 'Request':
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...
262
                /** @var Request $request */
263
                $request = Request::getById($objectId, $database);
264
                $name = htmlentities($request->getName(), ENT_COMPAT, 'UTF-8');
265
266
                return <<<HTML
267
<a href="{$baseurl}/internal.php/viewRequest?id={$objectId}">Request #{$objectId} ({$name})</a>
268
HTML;
269
            case 'User':
270
                /** @var User $user */
271
                $user = User::getById($objectId, $database);
272
                $username = htmlentities($user->getUsername(), ENT_COMPAT, 'UTF-8');
273
274
                return "<a href=\"{$baseurl}/internal.php/statistics/users/detail?user={$objectId}\">{$username}</a>";
275
            case 'WelcomeTemplate':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
276
                /** @var WelcomeTemplate $welcomeTemplate */
277
                $welcomeTemplate = WelcomeTemplate::getById($objectId, $database);
278
279
                // some old templates have been completely deleted and lost to the depths of time.
280
                if ($welcomeTemplate === false) {
281
                    return "Welcome template #{$objectId}";
282
                }
283
                else {
284
                    $userCode = htmlentities($welcomeTemplate->getUserCode(), ENT_COMPAT, 'UTF-8');
285
286
                    return "<a href=\"{$baseurl}/internal.php/welcomeTemplates/view?template={$objectId}\">{$userCode}</a>";
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 124 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
287
                }
288
            default:
289
                return '[' . $objectType . " " . $objectId . ']';
290
        }
291
    }
292
293
    /**
294
     * @param    Log[]          $logs
295
     * @param     PdoDatabase   $database
296
     * @param SiteConfiguration $configuration
297
     *
298
     * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array[].

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
299
     * @throws Exception
300
     */
301
    public static function prepareLogsForTemplate($logs, PdoDatabase $database, SiteConfiguration $configuration)
302
    {
303
        $userIds = array();
304
305
        /** @var Log $logEntry */
306
        foreach ($logs as $logEntry) {
307
            if (!$logEntry instanceof Log) {
308
                // if this happens, we've done something wrong with passing back the log data.
309
                throw new Exception('Log entry is not an instance of a Log, this should never happen.');
310
            }
311
312
            $user = $logEntry->getUser();
313
            if ($user === -1) {
314
                continue;
315
            }
316
317
            if (!array_search($user, $userIds)) {
318
                $userIds[] = $user;
319
            }
320
        }
321
322
        $users = UserSearchHelper::get($database)->inIds($userIds)->fetchColumn('username');
323
        $users[-1] = User::getCommunity()->getUsername();
324
325
        $logData = array();
326
327
        /** @var Log $logEntry */
328
        foreach ($logs as $logEntry) {
329
            $objectDescription = self::getObjectDescription($logEntry->getObjectId(), $logEntry->getObjectType(),
330
                $database, $configuration);
331
332
            if ($logEntry->getAction() === 'Renamed') {
333
                $renameData = unserialize($logEntry->getComment());
334
                $oldName = htmlentities($renameData['old'], ENT_COMPAT, 'UTF-8');
335
                $newName = htmlentities($renameData['new'], ENT_COMPAT, 'UTF-8');
336
                $comment = 'Renamed \'' . $oldName . '\' to \'' . $newName . '\'.';
337
            }
338
            else if ($logEntry->getAction() === 'RoleChange') {
339
                $roleChangeData = unserialize($logEntry->getComment());
340
341
                $removed = array();
342
                foreach ($roleChangeData['removed'] as $r) {
343
                    $removed[] = htmlentities($r, ENT_COMPAT, 'UTF-8');
344
                }
345
346
                $added = array();
347
                foreach ($roleChangeData['added'] as $r) {
348
                    $added[] = htmlentities($r, ENT_COMPAT, 'UTF-8');
349
                }
350
351
                $reason = htmlentities($roleChangeData['reason'], ENT_COMPAT, 'UTF-8');
352
353
                $roleDelta = 'Removed [' . implode(', ', $removed) . '], Added [' . implode(', ', $added) . ']';
354
                $comment = $roleDelta . ' with comment: ' . $reason;
355
            }
356
            else {
357
                $comment = $logEntry->getComment();
358
            }
359
360
            $logData[] = array(
361
                'timestamp'         => $logEntry->getTimestamp(),
362
                'userid'            => $logEntry->getUser(),
363
                'username'          => $users[$logEntry->getUser()],
364
                'description'       => self::getLogDescription($logEntry),
365
                'objectdescription' => $objectDescription,
366
                'comment'           => $comment,
367
            );
368
        }
369
370
        return array($users, $logData);
371
    }
372
}
373