Passed
Push — master ( 02a4a5...734a7e )
by Mihail
05:36
created

Comments   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 185
Duplicated Lines 4.86 %

Coupling/Cohesion

Components 1
Dependencies 15

Importance

Changes 10
Bugs 5 Features 0
Metric Value
c 10
b 5
f 0
dl 9
loc 185
rs 9.1666
wmc 21
lcom 1
cbo 15

4 Methods

Rating   Name   Duplication   Size   Complexity  
B actionShowanswers() 3 35 6
B actionAdd() 0 35 4
B actionList() 3 60 6
B actionCount() 3 26 5

How to fix   Duplicated Code   

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:

1
<?php
2
3
namespace Apps\Controller\Api;
4
5
use Apps\ActiveRecord\CommentPost;
6
use Apps\ActiveRecord\CommentAnswer;
7
use Apps\ActiveRecord\App as AppRecord;
8
use Apps\Model\Api\Comments\CommentAnswerAdd;
9
use Apps\Model\Api\Comments\CommentPostAdd;
10
use Apps\Model\Api\Comments\EntityCommentData;
11
use Extend\Core\Arch\ApiController;
12
use Ffcms\Core\App;
13
use Ffcms\Core\Helper\Type\Obj;
14
use Ffcms\Core\Helper\Type\Str;
15
use Ffcms\Core\Exception\NotFoundException;
16
use Ffcms\Core\Exception\NativeException;
17
use Ffcms\Core\Exception\ForbiddenException;
18
19
/**
20
 * Class Comments. View and add comments and answers via json based ajax query's
21
 * @package Apps\Controller\Api
22
 */
23
class Comments extends ApiController
24
{
25
    /**
26
     * Add comment or answer via ajax.
27
     * @return string
28
     * @throws NativeException
29
     */
30
    public function actionAdd()
31
    {
32
        $this->setJsonHeader();
33
        $configs = AppRecord::getConfigs('widget', 'Comments');
34
35
        $replayTo = (int)$this->request->request->get('replay-to');
0 ignored issues
show
Documentation introduced by
The property request does not exist on object<Apps\Controller\Api\Comments>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
36
        $model = null;
0 ignored issues
show
Unused Code introduced by
$model is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
37
        // check if its a answer (comment answer type)
38
        if ($replayTo > 0) {
39
            $model = new CommentAnswerAdd($configs);
0 ignored issues
show
Bug introduced by
It seems like $configs defined by \Apps\ActiveRecord\App::...s('widget', 'Comments') on line 33 can also be of type null or string; however, Apps\Model\Api\Comments\...nswerAdd::__construct() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
40
            $model->replayTo = $replayTo;
41
        } else { // sounds like new comment row
42
            $model = new CommentPostAdd($configs);
0 ignored issues
show
Bug introduced by
It seems like $configs defined by \Apps\ActiveRecord\App::...s('widget', 'Comments') on line 33 can also be of type null or string; however, Apps\Model\Api\Comments\...tPostAdd::__construct() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
43
            $model->pathway = App::$Security->strip_tags($this->request->request->get('pathway'));
0 ignored issues
show
Documentation introduced by
The property request does not exist on object<Apps\Controller\Api\Comments>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
44
        }
45
46
        // pass general comment params to model
47
        $model->message = App::$Security->secureHtml((string)$this->request->request->get('message'));
0 ignored issues
show
Documentation introduced by
The property request does not exist on object<Apps\Controller\Api\Comments>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
48
        $model->guestName = App::$Security->strip_tags($this->request->request->get('guest-name'));
0 ignored issues
show
Documentation introduced by
The property request does not exist on object<Apps\Controller\Api\Comments>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
49
50
        // check model conditions before add new row
51
        if ($model === null || !$model->check()) {
52
            throw new NativeException('Unknown error');
53
        }
54
55
        // add comment post or answer to database and get response active record row
56
        $record = $model->buildRecord();
57
        // pass row to entity builder model
58
        $response = new EntityCommentData($record);
59
60
        return json_encode([
61
            'status' => 1,
62
            'data' => $response->make() // build row to standard format
63
        ]);
64
    }
65
66
    /**
67
     * List comments as json object with defined offset index
68
     * @param int $index
69
     * @return string
70
     * @throws NotFoundException
71
     */
72
    public function actionList($index)
73
    {
74
        // set header
75
        $this->setJsonHeader();
76
        // get configs
77
        $configs = AppRecord::getConfigs('widget', 'Comments');
78
        // items per page
79
        $perPage = (int)$configs['perPage'];
80
        // offset can be only integer
81
        $index = (int)$index;
82
        $offset = $perPage * $index;
83
        // get comment target path and check
84
        $path = (string)$this->request->query->get('path');
0 ignored issues
show
Documentation introduced by
The property request does not exist on object<Apps\Controller\Api\Comments>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
85
        if (Str::likeEmpty($path)) {
86
            throw new NotFoundException('Wrong path');
87
        }
88
89
        // select comments from db and check it
90
        $query = CommentPost::where('pathway', '=', $path)
91
            ->where('moderate', '=', 0);
92
93
        // check if comments is depend of language locale
94 View Code Duplication
        if ((int)$configs['onlyLocale'] === 1) {
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...
95
            $query = $query->where('lang', '=', $this->request->getLanguage());
0 ignored issues
show
Documentation introduced by
The property request does not exist on object<Apps\Controller\Api\Comments>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
96
        }
97
98
        // get comments with offset and limit
99
        $records = $query->skip($offset)
100
            ->take($perPage)
101
            ->get();
102
103
        // check if records is not empty
104
        if ($records->count() < 1) {
105
            throw new NotFoundException(__('There is no comments found yet. You can be the first!'));
106
        }
107
108
        // build output json data as array
109
        $data = [];
110
        foreach ($records as $comment) {
111
            // prepare specified data to output response, based on entity model
112
            $commentResponse = new EntityCommentData($comment);
113
114
            // build output json data
115
            $data[] = $commentResponse->make();
116
            $commentResponse = null;
0 ignored issues
show
Unused Code introduced by
$commentResponse is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
117
        }
118
119
        // calculate comments left count
120
        $count = CommentPost::where('pathway', '=', $path)->where('moderate', '=', 0)->count();
121
        $count -= $offset + $perPage;
122
        if ($count < 0) {
123
            $count = 0;
124
        }
125
126
        return json_encode([
127
            'status' => 1,
128
            'data' => $data,
129
            'leftCount' => $count
130
        ]);
131
    }
132
133
    /**
134
     * List answers by comment id as json object
135
     * @param int $commentId
136
     * @return string
137
     * @throws ForbiddenException
138
     * @throws NotFoundException
139
     */
140
    public function actionShowanswers($commentId)
141
    {
142
        $this->setJsonHeader();
143
        // check input data
144
        if (!Obj::isLikeInt($commentId) || (int)$commentId < 1) {
145
            throw new ForbiddenException('Input data is incorrect');
146
        }
147
148
        // get configs
149
        $configs = AppRecord::getConfigs('widget', 'Comments');
150
151
        // get data from db by comment id
152
        $records = CommentAnswer::where('comment_id', '=', $commentId)
153
            ->where('moderate', '=', 0);
154 View Code Duplication
        if ((int)$configs['onlyLocale'] === 1) {
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...
155
            $records = $records->where('lang', '=', $this->request->getLanguage());
0 ignored issues
show
Documentation introduced by
The property request does not exist on object<Apps\Controller\Api\Comments>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
156
        }
157
158
        // check objects count
159
        if ($records->count() < 1) {
160
            throw new NotFoundException(__('No answers for comment is founded'));
161
        }
162
163
        // prepare output
164
        $response = [];
165
        foreach ($records->get() as $row) {
166
            $commentAnswer = new EntityCommentData($row);
167
            $response[] = $commentAnswer->make();
168
        }
169
170
        return json_encode([
171
            'status' => 1,
172
            'data' => $response
173
        ]);
174
    }
175
176
    /**
177
     * Get commentaries count for pathway. Pathway should be array [itemId => pathway]
178
     * @throws NativeException
179
     * @return string
180
     */
181
    public function actionCount()
182
    {
183
        // set headers
184
        $this->setJsonHeader();
185
        // get configs
186
        $configs = AppRecord::getConfigs('widget', 'Comments');
187
        // get path array from request
188
        $path = $this->request->query->get('path');
0 ignored issues
show
Documentation introduced by
The property request does not exist on object<Apps\Controller\Api\Comments>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
189
        if (!Obj::isArray($path) || count($path) < 1) {
190
            throw new NativeException('Wrong query params');
191
        }
192
193
        $count = [];
194
        // for each item in path array calculate comments count
195
        foreach ($path as $id => $uri) {
196
            $query = CommentPost::where('pathway', '=', $uri)->where('moderate', '=', 0);
197
            // check if comments is depend of language locale
198 View Code Duplication
            if ((int)$configs['onlyLocale'] === 1) {
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...
199
                $query = $query->where('lang', '=', $this->request->getLanguage());
0 ignored issues
show
Documentation introduced by
The property request does not exist on object<Apps\Controller\Api\Comments>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
200
            }
201
            // set itemId => count
202
            $count[(int)$id] = $query->count();
203
        }
204
        // render json response
205
        return json_encode(['status' => 1, 'count' => $count]);
206
    }
207
}