Passed
Push — edit-comment ( 1a3020...0abc2e )
by Simon
02:49
created

PageEditComment   A

Complexity

Total Complexity 40

Size/Duplication

Total Lines 161
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 3
Bugs 0 Features 0
Metric Value
wmc 40
eloc 76
dl 0
loc 161
ccs 0
cts 77
cp 0
rs 9.2
c 3
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
D main() 0 82 19
C checkCommentAccess() 0 30 14
A redirectBack() 0 8 2
A updateCommentData() 0 12 5

How to fix   Complexity   

Complex Class

Complex classes like PageEditComment often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use PageEditComment, and based on these observations, apply Extract Interface, too.

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 Waca\DataObjects\Comment;
13
use Waca\DataObjects\Request;
14
use Waca\DataObjects\User;
15
use Waca\Exceptions\AccessDeniedException;
16
use Waca\Exceptions\ApplicationLogicException;
17
use Waca\Helpers\Logger;
18
use Waca\SessionAlert;
19
use Waca\Tasks\InternalPageBase;
20
use Waca\WebRequest;
21
22
class PageEditComment extends InternalPageBase
23
{
24
    /**
25
     * Main function for this page, when no specific actions are called.
26
     * @throws ApplicationLogicException
27
     * @throws Exception
28
     */
29
    protected function main()
30
    {
31
        $commentId = WebRequest::getInt('id');
32
        if ($commentId === null) {
33
            throw new ApplicationLogicException('Comment ID not specified');
34
        }
35
36
        $database = $this->getDatabase();
37
38
        /** @var Comment|false $comment */
39
        $comment = Comment::getById($commentId, $database);
40
        if ($comment === false) {
0 ignored issues
show
introduced by
The condition $comment === false is always false.
Loading history...
41
            throw new ApplicationLogicException('Comment not found');
42
        }
43
44
        $currentUser = User::getCurrent($database);
45
46
        $this->checkCommentAccess($comment, $currentUser);
47
48
        /** @var Request|false $request */
49
        $request = Request::getById($comment->getRequest(), $database);
50
51
        if ($request === false) {
0 ignored issues
show
introduced by
The condition $request === false is always false.
Loading history...
52
            throw new ApplicationLogicException('Request was not found.');
53
        }
54
55
        $canUnflag = $this->barrierTest('unflag', $currentUser, PageFlagComment::class);
56
57
        if (WebRequest::wasPosted()) {
58
            $this->validateCSRFToken();
59
            $newComment = WebRequest::postString('newcomment');
60
            $visibility = WebRequest::postString('visibility');
61
            $doUnflag = WebRequest::postBoolean('unflag');
62
63
            if ($newComment === null || $newComment === "") {
64
                throw new ApplicationLogicException("Comment cannot be empty!");
65
            }
66
67
            $commentDataUnchanged = $newComment === $comment->getComment()
68
                && ($comment->getVisibility() === 'requester' || $comment->getVisibility() === $visibility);
69
            $flagStatusUnchanged = (!$canUnflag || $comment->getFlagged() && !$doUnflag);
70
71
            if ($commentDataUnchanged && $flagStatusUnchanged) {
72
                // No change was made; redirect back.
73
                $this->redirectBack($comment->getRequest());
74
                return;
75
            }
76
77
            // optimistically lock from the load of the edit comment form
78
            $updateVersion = WebRequest::postInt('updateversion');
79
80
            // comment data has changed, update the object
81
            if (!$commentDataUnchanged) {
82
                $this->updateCommentData($comment, $visibility, $newComment);
83
            }
84
85
            if ($doUnflag && $canUnflag) {
86
                $comment->setFlagged(false);
87
            }
88
89
            $comment->setUpdateVersion($updateVersion);
90
            $comment->save();
91
92
            if (!$commentDataUnchanged) {
93
                Logger::editComment($database, $comment, $request);
94
                $this->getNotificationHelper()->commentEdited($comment, $request);
95
            }
96
97
            if ($doUnflag && $canUnflag) {
98
                Logger::unflaggedComment($database, $comment, $request->getDomain());
99
            }
100
101
            SessionAlert::success("Comment has been saved successfully");
102
            $this->redirectBack($comment->getRequest());
103
        }
104
        else {
105
            $this->assignCSRFToken();
106
            $this->assign('comment', $comment);
107
            $this->assign('request', $request);
108
            $this->assign('user', User::getById($comment->getUser(), $database));
109
            $this->assign('canUnflag', $canUnflag);
110
            $this->setTemplate('edit-comment.tpl');
111
        }
112
    }
113
114
    /**
115
     * @param $comment
116
     * @param $currentUser
117
     *
118
     * @return void
119
     * @throws AccessDeniedException
120
     */
121
    protected function checkCommentAccess($comment, $currentUser): void
122
    {
123
        if ($comment->getUser() !== $currentUser->getId() && !$this->barrierTest('editOthers', $currentUser)) {
124
            throw new AccessDeniedException($this->getSecurityManager(), $this->getDomainAccessManager());
125
        }
126
127
        $restrictedVisibility = $comment->getFlagged()
128
            || $comment->getVisibility() === 'admin'
129
            || $comment->getVisibility() === 'checkuser';
130
131
        if ($restrictedVisibility && !$this->barrierTest('alwaysSeePrivateData', $currentUser, 'RequestData')) {
132
            // Restricted visibility comments can only be seen if the user has a request reserved.
133
            /** @var Request $request */
134
            $request = Request::getById($comment->getRequest(), $comment->getDatabase());
135
136
            if ($request->getReserved() !== $currentUser->getId()) {
137
                throw new AccessDeniedException($this->getSecurityManager(), $this->getDomainAccessManager());
138
            }
139
        }
140
141
        if ($comment->getVisibility() === 'admin'
142
            && !$this->barrierTest('seeRestrictedComments', $currentUser, 'RequestData')
143
            && $comment->getUser() !== $currentUser->getId()) {
144
            throw new AccessDeniedException($this->getSecurityManager(), $this->getDomainAccessManager());
145
        }
146
147
        if ($comment->getVisibility() === 'checkuser'
148
            && !$this->barrierTest('seeCheckuserComments', $currentUser, 'RequestData')
149
            && $comment->getUser() !== $currentUser->getId()) {
150
            throw new AccessDeniedException($this->getSecurityManager(), $this->getDomainAccessManager());
151
        }
152
    }
153
154
    /**
155
     * @param             $comment
156
     * @param string|null $visibility
157
     * @param             $newComment
158
     *
159
     * @throws ApplicationLogicException
160
     */
161
    protected function updateCommentData(Comment $comment, ?string $visibility, string $newComment): void
162
    {
163
        if ($comment->getVisibility() !== 'requester') {
164
            if ($visibility !== 'user' && $visibility !== 'admin' && $visibility !== 'checkuser') {
165
                throw new ApplicationLogicException('Comment visibility is not valid');
166
            }
167
168
            $comment->setVisibility($visibility);
169
        }
170
171
        $comment->setComment($newComment);
172
        $comment->touchEdited();
173
    }
174
175
    protected function redirectBack(int $requestId): void
176
    {
177
        $source = WebRequest::getString("from");
178
179
        if ($source == "flagged") {
180
            $this->redirect('flaggedComments');
181
        } else {
182
            $this->redirect('viewRequest', null, array('id' => $requestId));
183
        }
184
    }
185
}
186