Completed
Push — master ( 06d4ad...d5ac2f )
by Emil
02:11
created

CommentController   B

Complexity

Total Complexity 41

Size/Duplication

Total Lines 288
Duplicated Lines 8.33 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 22.01%

Importance

Changes 0
Metric Value
wmc 41
lcom 1
cbo 2
dl 24
loc 288
ccs 35
cts 159
cp 0.2201
rs 8.2769
c 0
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
B showComments() 9 31 4
A init() 0 10 1
B replyComment() 9 40 6
B editComment() 3 46 6
B deleteComment() 3 39 6
B voteComment() 0 22 5
A getComments() 0 11 2
A sortBy() 0 6 2
A buildCommentTree() 0 18 4
B sortBranchComments() 0 21 5

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like CommentController 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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

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 CommentController, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Emsa\Comment;
4
5
use \Anax\DI\InjectionAwareInterface;
6
use \Anax\DI\InjectionAwareTrait;
7
use \LRC\Form\ModelForm as Modelform;
8
9
/**
10
 * A controller for the comment system.
11
 */
12
class CommentController implements InjectionAwareInterface
13
{
14
    use InjectionAwareTrait;
15
16
17
18
    /**
19
     * @var \LRC\Repository\SoftDbRepository  Comment repository.
20
     */
21
    private $comments;
22
23
24
25
    /**
26
     * Configuration.
27
     */
28 1
    public function init()
29
    {
30 1
        $commentRepository = $this->di->manager->createRepository(Comment::class, [
31 1
            'db' => $this->di->db,
32 1
            'type' => 'db-soft',
33 1
            'table' => 'rv1_Comment'
34
        ]);
35 1
        $this->comments = $commentRepository;
36 1
        return $commentRepository;
37
    }
38
39
40
41
    public function showComments($postid)
42
    {
43
        $newForm = new ModelForm('new-comment-form', Comment::class);
44
        $loggedInUser = $this->di->userController->getLoggedInUserId();
45
46 View Code Duplication
        if ($this->di->request->getMethod() == 'POST' && $this->di->session->has("username")) {
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...
47
            $comment = $newForm->populateModel();
48
            $newForm->validate();
49
            if ($newForm->isValid()) {
50
                $comment->user = $loggedInUser;
51
                $this->comments->save($comment);
52
                $this->di->response->redirect("comment/$postid#{$comment->id}");
53
            }
54
        }
55
56
        $comments = $this->getComments($postid, $loggedInUser);
57
        $sortBy = $this->sortBy();
58
        $sortedComments = $this->buildCommentTree($comments, $sortBy);
59
60
        $viewData = [
61
            "comments" => $sortedComments,
62
            "textfilter" => $this->di->textfilter,
63
            "postid" => $postid,
64
            "action" => "",
65
            "actionID" => "",
66
            "newForm" => $newForm,
67
            "isLoggedIn" => $this->di->session->has("username")
68
        ];
69
70
        $this->di->view->add("comment/comment-section", $viewData, "main", 2);
71
    }
72
73
74
75
    public function replyComment($postid)
76
    {
77
        $actionID = (int)$this->di->request->getGet("id");
78
        $loggedInUser = $this->di->userController->getLoggedInUserId();
79
80
        if ($this->di->request->getMethod() == 'GET' && (!$this->comments->find('id', $actionID) || !$this->di->session->has("username"))) {
81
            $this->di->response->redirect("comment/$postid");
82
        }
83
84
        $replyForm = new ModelForm('reply-comment-form', Comment::class);
85
86 View Code Duplication
        if ($this->di->request->getMethod() == 'POST') {
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...
87
            $comment = $replyForm->populateModel();
88
            $replyForm->validate();
89
            if ($replyForm->isValid()) {
90
                $comment->user = $loggedInUser;
91
                $this->comments->save($comment);
92
                $this->di->response->redirect("comment/$postid#{$comment->id}");
93
            }
94
        }
95
96
        $newForm = new ModelForm('new-comment-form', Comment::class);
97
98
        $comments = $this->getComments($postid, $loggedInUser);
99
        $sortBy = $this->sortBy();
100
        $sortedComments = $this->buildCommentTree($comments, $sortBy);
101
102
        $viewData = [
103
            "comments" => $sortedComments,
104
            "textfilter" => $this->di->textfilter,
105
            "postid" => $postid,
106
            "action" => "reply",
107
            "actionID" => $actionID,
108
            "newForm" => $newForm,
109
            "replyForm" => $replyForm,
110
            "isLoggedIn" => $this->di->session->has("username")
111
        ];
112
113
        $this->di->view->add("comment/comment-section", $viewData, "main", 2);
114
    }
115
116
117
118
    public function editComment($postid)
119
    {
120
        $actionID = (int)$this->di->request->getGet("id");
121
122
        $currentComment = $this->comments->findSoft('id', $actionID);
123
        if (!$currentComment) {
124
            $this->di->response->redirect("comment/$postid");
125
        }
126
127
        $loggedInUser = $this->di->userController->getLoggedInUserId();
128 View Code Duplication
        if ($loggedInUser != $currentComment->user && !$this->di->session->has("admin")) {
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...
129
            $this->di->response->redirect("comment/$postid");
130
        }
131
132
        $editForm = new ModelForm('edit-comment-form', $currentComment);
133
134
        if ($this->di->request->getMethod() == 'POST') {
135
            $comment = $editForm->populateModel(null, ['id', 'post_id', 'parent_id']);
136
            //Prevent edited column from being set to NULL
137
            unset($comment->edited);
138
            $editForm->validate();
139
            if ($editForm->isValid()) {
140
                $this->comments->save($comment);
141
                $this->di->response->redirect("comment/$postid#{$comment->id}");
142
            }
143
        }
144
145
        $newForm = new ModelForm('new-comment-form', Comment::class);
146
147
        $comments = $this->getComments($postid, $loggedInUser);
148
        $sortBy = $this->sortBy();
149
        $sortedComments = $this->buildCommentTree($comments, $sortBy);
150
151
        $viewData = [
152
            "comments" => $sortedComments,
153
            "textfilter" => $this->di->textfilter,
154
            "postid" => $postid,
155
            "action" => "edit",
156
            "actionID" => $actionID,
157
            "newForm" => $newForm,
158
            "editForm" => $editForm,
159
            "isLoggedIn" => $this->di->session->has("username")
160
        ];
161
162
        $this->di->view->add("comment/comment-section", $viewData, "main", 2);
163
    }
164
165
166
167
    public function deleteComment($postid)
168
    {
169
        $actionID = (int)$this->di->request->getGet("id");
170
171
        $currentComment = $this->comments->findSoft('id', $actionID);
172
        if (!$currentComment) {
173
            $this->di->response->redirect("comment/$postid");
174
        }
175
176
        $loggedInUser = $this->di->userController->getLoggedInUserId();
177 View Code Duplication
        if ($loggedInUser != $currentComment->user && !$this->di->session->has("admin")) {
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...
178
            $this->di->response->redirect("comment/$postid");
179
        }
180
181
        if ($this->di->request->getMethod() == 'POST') {
182
            if ($this->di->request->getPost('delete') == 'Ja') {
183
                $this->comments->deleteSoft($currentComment);
184
            }
185
            $this->di->response->redirect("comment/$postid#{$currentComment->id}");
186
        }
187
188
        $newForm = new ModelForm('new-comment-form', Comment::class);
189
190
        $comments = $this->getComments($postid, $loggedInUser);
191
        $sortBy = $this->sortBy();
192
        $sortedComments = $this->buildCommentTree($comments, $sortBy);
193
194
        $viewData = [
195
            "comments" => $sortedComments,
196
            "textfilter" => $this->di->textfilter,
197
            "postid" => $postid,
198
            "action" => "delete",
199
            "actionID" => $actionID,
200
            "newForm" => $newForm,
201
            "isLoggedIn" => $this->di->session->has("username")
202
        ];
203
204
        $this->di->view->add("comment/comment-section", $viewData, "main", 2);
205
    }
206
207
208
209
    public function voteComment($postid)
210
    {
211
        $actionID = (int)$this->di->request->getGet("id");
212
213
        $comment = $this->comments->findSoft('id', $actionID);
214
        if (!$comment) {
215
            $this->di->response->redirect("comment/$postid");
216
        }
217
218
        if (!$this->di->session->has("username")) {
219
            $this->di->response->redirect("comment/$postid");
220
        }
221
222
        if ($this->di->request->getPost("upvote")) {
223
            $comment->upvote += 1;
224
        } elseif ($this->di->request->getPost("downvote")) {
225
            $comment->downvote += 1;
226
        }
227
228
        $this->comments->save($comment);
229
        $this->di->response->redirect("comment/$postid#{$comment->id}");
230
    }
231
232
233
234
    public function getComments($postid, $loggedInUser)
235
    {
236
        $comments = $this->comments->getAll('post_id = ?', [$postid]);
237
238
        foreach ($comments as $comment) {
239
            $comment->isUserOwner = ($loggedInUser == $comment->userObject->id);
240
            $comment->isUserAdmin = $this->di->session->has("admin");
241
        }
242
243
        return $comments;
244
    }
245
246
247
248 1
    public function sortBy()
249
    {
250 1
        $sortRequest = $this->di->request->getGet("sort");
251 1
        $sortRules = ["best", "old", "new"];
252 1
        return in_array($sortRequest, $sortRules) ? $sortRequest : "best";
253
    }
254
255
256
257 1
    public function buildCommentTree(array &$elements, $sortBy, $parentId = 0)
258
    {
259 1
        $branch = array();
260
261 1
        foreach ($elements as $element) {
262 1
            if ($element->parent_id == $parentId) {
263 1
                $children = $this->buildCommentTree($elements, $sortBy, $element->id);
264 1
                if (!empty($children)) {
265 1
                    $element->children = $children;
266
                }
267 1
                $branch[$element->id] = $element;
268
                // Ingen aning varför jag haft unset tidigare, och nu funkar det inte som tidigare heller
269
                // unset($elements[$element->id]);
270
            }
271
        }
272 1
        $this->sortBranchComments($branch, $sortBy);
273 1
        return $branch;
274
    }
275
276
277
278 2
    public function sortBranchComments(array &$branch, $sortBy = "best")
279
    {
280 2
        $sortOrder = SORT_DESC;
281 2
        $sortArray = array();
282 2
        foreach ($branch as $key => $comment) {
283
            switch ($sortBy) {
284 2
                case 'old':
285 1
                    $sortOrder = SORT_ASC;
286
                    //Intentional fall through
287 2
                case 'new':
288 1
                    $sortArray[$key] = $comment->created;
289 1
                    break;
290 2
                case 'best':
291
                    //Intentional fall through
292
                default:
293 2
                    $sortArray[$key] = ($comment->upvote - $comment->downvote);
294 2
                    break;
295
            }
296
        }
297 2
        array_multisort($sortArray, $sortOrder, $branch);
298 2
    }
299
}
300