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

PageEditComment::checkCommentAccess()   C

Complexity

Conditions 14
Paths 22

Size

Total Lines 30
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 210

Importance

Changes 0
Metric Value
eloc 17
dl 0
loc 30
ccs 0
cts 18
cp 0
rs 6.2666
c 0
b 0
f 0
cc 14
nc 22
nop 2
crap 210

How to fix   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\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