Test Setup Failed
Push — master ( 5f75b5...a576a1 )
by Simon
03:23
created

PageEditComment::redirectBack()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 9
ccs 0
cts 0
cp 0
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 6
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
75
                return;
76
            }
77
78
            // optimistically lock from the load of the edit comment form
79
            $updateVersion = WebRequest::postInt('updateversion');
80
81
            // comment data has changed, update the object
82
            if (!$commentDataUnchanged) {
83
                $this->updateCommentData($comment, $visibility, $newComment);
84
            }
85
86
            if ($doUnflag && $canUnflag) {
87
                $comment->setFlagged(false);
88
            }
89
90
            $comment->setUpdateVersion($updateVersion);
91
            $comment->save();
92
93
            if (!$commentDataUnchanged) {
94
                Logger::editComment($database, $comment, $request);
95
                $this->getNotificationHelper()->commentEdited($comment, $request);
96
            }
97
98
            if ($doUnflag && $canUnflag) {
99
                Logger::unflaggedComment($database, $comment, $request->getDomain());
100
            }
101
102
            SessionAlert::success('Comment has been saved successfully');
103
            $this->redirectBack($comment->getRequest());
104
        }
105
        else {
106
            $this->assignCSRFToken();
107
            $this->assign('comment', $comment);
108
            $this->assign('request', $request);
109
            $this->assign('user', User::getById($comment->getUser(), $database));
110
            $this->assign('canUnflag', $canUnflag);
111
            $this->setTemplate('edit-comment.tpl');
112
        }
113
    }
114
115
    /**
116
     * @throws AccessDeniedException
117
     */
118
    private function checkCommentAccess(Comment $comment, User $currentUser): void
119
    {
120
        if ($comment->getUser() !== $currentUser->getId() && !$this->barrierTest('editOthers', $currentUser)) {
121
            throw new AccessDeniedException($this->getSecurityManager(), $this->getDomainAccessManager());
122
        }
123
124
        $restrictedVisibility = $comment->getFlagged()
125
            || $comment->getVisibility() === 'admin'
126
            || $comment->getVisibility() === 'checkuser';
127
128
        if ($restrictedVisibility && !$this->barrierTest('alwaysSeePrivateData', $currentUser, 'RequestData')) {
129
            // Restricted visibility comments can only be seen if the user has a request reserved.
130
            /** @var Request $request */
131
            $request = Request::getById($comment->getRequest(), $comment->getDatabase());
132
133
            if ($request->getReserved() !== $currentUser->getId()) {
134
                throw new AccessDeniedException($this->getSecurityManager(), $this->getDomainAccessManager());
135
            }
136
        }
137
138
        if ($comment->getVisibility() === 'admin'
139
            && !$this->barrierTest('seeRestrictedComments', $currentUser, 'RequestData')
140
            && $comment->getUser() !== $currentUser->getId()) {
141
            throw new AccessDeniedException($this->getSecurityManager(), $this->getDomainAccessManager());
142
        }
143
144
        if ($comment->getVisibility() === 'checkuser'
145
            && !$this->barrierTest('seeCheckuserComments', $currentUser, 'RequestData')
146
            && $comment->getUser() !== $currentUser->getId()) {
147
            throw new AccessDeniedException($this->getSecurityManager(), $this->getDomainAccessManager());
148
        }
149
    }
150
151
    /**
152
     * @throws ApplicationLogicException
153
     */
154
    private function updateCommentData(Comment $comment, ?string $visibility, string $newComment): void
155
    {
156
        if ($comment->getVisibility() !== 'requester') {
157
            if ($visibility !== 'user' && $visibility !== 'admin' && $visibility !== 'checkuser') {
158
                throw new ApplicationLogicException('Comment visibility is not valid');
159
            }
160
161
            $comment->setVisibility($visibility);
162
        }
163
164
        $comment->setComment($newComment);
165
        $comment->touchEdited();
166
    }
167
168
    private function redirectBack(int $requestId): void
169
    {
170
        $source = WebRequest::getString('from');
171
172
        if ($source == 'flagged') {
173
            $this->redirect('flaggedComments');
174
        }
175
        else {
176
            $this->redirect('viewRequest', null, array('id' => $requestId));
177
        }
178
    }
179
}
180