Completed
Pull Request — master (#181)
by
unknown
13:57
created

ReportsTable   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 322
Duplicated Lines 4.66 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 93.94%

Importance

Changes 0
Metric Value
wmc 22
lcom 1
cbo 5
dl 15
loc 322
ccs 93
cts 99
cp 0.9394
rs 10
c 0
b 0
f 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
A initialize() 0 6 1
A getIncidents() 0 10 1
A getRelatedReports() 0 6 1
A getIncidentsWithDescription() 0 12 1
A getIncidentsWithDifferentStacktrace() 0 9 1
A removeFromRelatedGroup() 0 19 2
A addToRelatedGroup() 0 13 3
A getUrl() 0 5 1
A setLinkedReportStatus() 0 11 1
A _relatedIncidentsConditions() 0 12 2
A _relatedReportsConditions() 0 13 2
B getRelatedByField() 15 69 6

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
/* vim: set expandtab sw=4 ts=4 sts=4: */
4
/**
5
 * Report model representing a group of incidents.
6
 *
7
 * phpMyAdmin Error reporting server
8
 * Copyright (c) phpMyAdmin project (https://www.phpmyadmin.net/)
9
 *
10
 * Licensed under The MIT License
11
 * For full copyright and license information, please see the LICENSE.txt
12
 * Redistributions of files must retain the above copyright notice.
13
 *
14
 * @copyright Copyright (c) phpMyAdmin project (https://www.phpmyadmin.net/)
15
 * @license   https://opensource.org/licenses/mit-license.php MIT License
16
 *
17
 * @see      https://www.phpmyadmin.net/
18
 */
19
20
namespace App\Model\Table;
21
22
use Cake\Model\Model;
23
use Cake\ORM\Table;
24
use Cake\ORM\TableRegistry;
25
use Cake\Routing\Router;
26
27
/**
28
 * A report a representing a group of incidents.
29
 */
30
class ReportsTable extends Table
31
{
32
    /**
33
     * @var array
34
     *
35
     * @see http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#hasmany
36
     * @see Cake::Model::$hasMany
37
     */
38
    public $hasMany = array(
39
        'Incidents' => array(
40
            'dependant' => true,
41
        ),
42
    );
43
44
    /**
45
     * @var array
46
     *
47
     * @see http://book.cakephp.org/2.0/en/models/model-attributes.html#validate
48
     * @see http://book.cakephp.org/2.0/en/models/data-validation.html
49
     * @see Model::$validate
50
     */
51
    public $validate = array(
52
        'error_message' => array(
53
            'rule' => 'notEmpty',
54
            'required' => true,
55
        ),
56
    );
57
58
    /**
59
     * List of valid finder method options, supplied as the first parameter to find().
60
     *
61
     * @var array
62
     *
63
     * @see Model::$findMethods
64
     */
65
    public $findMethods = array(
66
        'allDataTable' => true,
67
        'arrayList' => true,
68
    );
69
70
    /**
71
     * List of valid finder method options, supplied as the first parameter to find().
72
     *
73
     * @var array
74
     */
75
    public $status = array(
76
        'new' => 'New',
77
        'invalid' => 'Invalid',
78
        'resolved' => 'Resolved',
79
        'forwarded' => 'Forwarded',
80
    );
81
82 25
    public function initialize(array $config)
83
    {
84 25
        $this->hasMany('Incidents', array(
85 25
            'dependent' => true,
86
        ));
87 25
    }
88
89
    /**
90
     * Retrieves the incident records that are related to the current report.
91
     *
92
     * @return array the list of incidents ordered by creation date desc
93
     */
94 4
    public function getIncidents()
95
    {
96 4
        $incidents = TableRegistry::get('Incidents')->find('all', array(
0 ignored issues
show
Deprecated Code introduced by
The method Cake\ORM\TableRegistry::get() has been deprecated with message: 3.6.0 Use \Cake\ORM\Locator\TableLocator::get() instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
97 4
            'limit' => 50,
98 4
            'conditions' => $this->_relatedIncidentsConditions(),
99 4
            'order' => 'Incidents.created desc',
100
        ));
101
102 4
        return $incidents;
103
    }
104
105
    /**
106
     * Retrieves the report records that are related to the current report.
107
     *
108
     * @return array the list of related reports
109
     */
110 2
    public function getRelatedReports()
111
    {
112 2
        return $this->find('all', array(
113 2
            'conditions' => $this->_relatedReportsConditions(),
114
        ));
115
    }
116
117
    /**
118
     * Retrieves the incident records that are related to the current report that
119
     * also have a description.
120
     *
121
     * @return array the list of incidents ordered by description lenght desc
122
     */
123 3
    public function getIncidentsWithDescription()
124
    {
125 3
        return TableRegistry::get('Incidents')->find('all', array(
0 ignored issues
show
Deprecated Code introduced by
The method Cake\ORM\TableRegistry::get() has been deprecated with message: 3.6.0 Use \Cake\ORM\Locator\TableLocator::get() instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
126 3
            'conditions' => array(
127
                'NOT' => array(
128
                    'Incidents.steps is null',
129
                ),
130 3
                $this->_relatedIncidentsConditions(),
131
            ),
132 3
            'order' => 'Incidents.steps desc',
133
        ));
134
    }
135
136
    /**
137
     * Retrieves the incident records that are related to the current report that
138
     * that have a different stacktrace.
139
     *
140
     * @return array the list of incidents
141
     */
142 3
    public function getIncidentsWithDifferentStacktrace()
143
    {
144 3
        return TableRegistry::get('Incidents')->find('all', array(
0 ignored issues
show
Deprecated Code introduced by
The method Cake\ORM\TableRegistry::get() has been deprecated with message: 3.6.0 Use \Cake\ORM\Locator\TableLocator::get() instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
145 3
            'fields' => array('DISTINCT Incidents.stackhash', 'Incidents.stacktrace',
146
                    'Incidents.full_report', 'Incidents.exception_type', ),
147 3
            'conditions' => $this->_relatedIncidentsConditions(),
148 3
            'group' => 'Incidents.stackhash',
149
        ));
150
    }
151
152
    /**
153
     * Removes a report from a group of related reports.
154
     *
155
     * @param mixed $report
156
     */
157 1
    public function removeFromRelatedGroup($report)
158
    {
159 1
        $report->related_to = null;
160 1
        $this->save($report);
161
162 1
        $rel_report = $this->findByRelatedTo($report->id)->first();
0 ignored issues
show
Documentation Bug introduced by
The method findByRelatedTo does not exist on object<App\Model\Table\ReportsTable>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
163 1
        if ($rel_report) {
164
            $this->updateAll(
165
                array('related_to' => $rel_report->id),
166
                array('related_to' => $report->id)
167
            );
168
        }
169
170
        // remove all redundant self-groupings
171 1
        $this->updateAll(
172 1
            array('related_to' => null),
173 1
            array('reports.related_to = reports.id')
174
        );
175 1
    }
176
177
    /**
178
     * Adds a report to a group of related reports.
179
     *
180
     * @param mixed $report
181
     * @param mixed $related_to
182
     */
183 1
    public function addToRelatedGroup($report, $related_to)
184
    {
185 1
        $dup_report = $this->get($related_to);
186
187 1
        if ($dup_report && $dup_report->related_to) {
0 ignored issues
show
Bug introduced by
Accessing related_to on the interface Cake\Datasource\EntityInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
188
            $report->related_to = $dup_report->related_to;
0 ignored issues
show
Bug introduced by
Accessing related_to on the interface Cake\Datasource\EntityInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
189
        } else {
190 1
            $report->related_to = $related_to;
191
        }
192 1
        $report->status = $dup_report->status;
0 ignored issues
show
Bug introduced by
Accessing status on the interface Cake\Datasource\EntityInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
193
194 1
        $this->save($report);
195 1
    }
196
197
    /**
198
     * Returns the full url to the current report.
199
     *
200
     * @return string url
201
     */
202 1
    public function getUrl()
203
    {
204 1
        return Router::url(array('controller' => 'reports', 'action' => 'view',
205 1
                $this->id, ), true);
206
    }
207
208
    /**
209
     * groups related incidents by distinct values of a field. It may also provide
210
     * the number of groups, whether to only include incidents that are related
211
     * to the current report and also to only limit the search to incidents
212
     * submited after a certain date.
213
     *
214
     * @param string $fieldName the name of the field to group by
215
     * @param int    $limit     the max number of groups to return
216
     * @param bool   $count     whether to return the number of distinct groups
217
     * @param bool   $related   whether to limit the search to only related incidents
218
     * @param Date   $timeLimit the date at which to start the search
219
     *
220
     * @return array the groups with the count of each group and possibly the number
221
     *               of groups. Ex: array('Apache' => 2) or array(array('Apache' => 2), 1)
222
     */
223 4
    public function getRelatedByField($fieldName, $limit = 10, $count = false,
224
        $related = true, $timeLimit = null)
225
    {
226 4
        $fieldAlias = "Incidents__$fieldName";
227
        $queryDetails = array(
228
            'conditions' => array(
229
                'NOT' => array(
230 4
                    "Incidents.$fieldName is null",
231
                ),
232
            ),
233 4
            'limit' => $limit,
234
        );
235
236 4
        if ($related) {
237 3
            $queryDetails['conditions'][] = $this->_relatedIncidentsConditions();
238
        }
239
240 4
        if ($timeLimit) {
241 2
            $queryDetails['conditions'][] = array(
242 2
                'Incidents.created >=' => $timeLimit,
243
            );
244
        }
245
246 4
        $groupedCount = TableRegistry::get('Incidents')->find('all', $queryDetails);
0 ignored issues
show
Deprecated Code introduced by
The method Cake\ORM\TableRegistry::get() has been deprecated with message: 3.6.0 Use \Cake\ORM\Locator\TableLocator::get() instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
247
248
        /* Ommit version number in case of browser and server_software fields.
249
         * In case of browser field, version number is seperated by space,
250
         * for example,'FIREFOX 47', hence split the value using space.
251
         * In case of server_software field, version number is seperated by /
252
         * for example, 'nginx/1.7', hence split the value using /.
253
         * See http://book.cakephp.org/3.0/en/orm/query-builder.html#using-sql-functionsp://book.cakephp.org/3.0/en/orm/query-builder.html#using-sql-functions
254
         * for how to use Sql functions with cake
255
         */
256
        switch ($fieldName) {
257 4 View Code Duplication
            case 'browser':
258
                // SUBSTRING(browser, 1, LOCATE(' ', Incidents.browser)-1))
259 3
                $field = $groupedCount->func()->substring(array(
260 3
                    $fieldName => 'literal',
261 3
                    '1' => 'literal',
262 3
                    "Locate(' ', Incidents.browser)-1" => 'literal',
263
                    ));
264 3
                break;
265 4 View Code Duplication
            case 'server_software':
266
                // SUBSTRING(server_software, 1, LOCATE('/', Incidents.server_software)-1))
267 3
                $field = $groupedCount->func()->substring(array(
268 3
                    $fieldName => 'literal', '1' => 'literal',
269 3
                    "Locate('/', Incidents.server_software)-1" => 'literal',
270
                    ));
271 3
                break;
272
            default:
273 4
                $field = $fieldName;
274
        }
275 4
        $groupedCount->select(array(
276 4
            'count' => $groupedCount->func()->count('*'),
277 4
            $fieldAlias => $field,
278 4
        ))->group($fieldAlias)->distinct(array("$fieldAlias"))
279 4
          ->order('count')->toArray();
280
281 4
        if ($count) {
282 3
            $queryDetails['fields'] = array("$fieldName");
283 3
            $queryDetails['limit'] = null;
284 3
            $queryDetails['group'] = "Incidents.$fieldName";
285 3
            $totalCount = TableRegistry::get('Incidents')->find('all', $queryDetails)->count();
0 ignored issues
show
Deprecated Code introduced by
The method Cake\ORM\TableRegistry::get() has been deprecated with message: 3.6.0 Use \Cake\ORM\Locator\TableLocator::get() instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
286
287 3
            return array($groupedCount, $totalCount);
288
        }
289
290 2
        return $groupedCount;
291
    }
292
293
    /**
294
     * Updates the linked reports to a Github issue to newly recieved status.
295
     *
296
     * @param string $issueNumber Github Issue number
297
     * @param string $status      New status to be set
298
     *
299
     * @return int Number of Linked reports updated
300
     */
301 1
    public function setLinkedReportStatus($issueNumber, $status)
302
    {
303
        $conditions = array(
304 1
            'sourceforge_bug_id' => $issueNumber,
305
        );
306
        $fields = array(
307 1
            'status' => $status,
308
        );
309
310 1
        return $this->updateAll($fields, $conditions);
311
    }
312
313
    /**
314
     * returns an array of conditions that would return all related incidents to the
315
     * current report.
316
     *
317
     * @return array the related incidents conditions
318
     */
319 7
    protected function _relatedIncidentsConditions()
320
    {
321
        $conditions = array(
322 7
            array('Incidents.report_id = ' . $this->id),
323
        );
324 7
        $report = $this->get($this->id);
325 7
        if ($report->related_to) { //TODO: fix when fix related reports
0 ignored issues
show
Bug introduced by
Accessing related_to on the interface Cake\Datasource\EntityInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
326 1
            $conditions[] = array('Incidents.report_id = ' . $report->related_to);
0 ignored issues
show
Bug introduced by
Accessing related_to on the interface Cake\Datasource\EntityInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
327
        }
328
329 7
        return array('OR' => $conditions);
330
    }
331
332
    /**
333
     * returns an array of conditions that would return all related reports to the
334
     * current report.
335
     *
336
     * @return array the related reports conditions
337
     */
338 2
    protected function _relatedReportsConditions()
339
    {
340 2
        $conditions = array(array('related_to' => $this->id));
341 2
        $report = $this->get($this->id);
342 2
        if ($report->related_to) { //TODO: fix related to
0 ignored issues
show
Bug introduced by
Accessing related_to on the interface Cake\Datasource\EntityInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
343
            $conditions[] = array('related_to' => $report->related_to);
0 ignored issues
show
Bug introduced by
Accessing related_to on the interface Cake\Datasource\EntityInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
344
            $conditions[] = array('id' => $report->related_to);
0 ignored issues
show
Bug introduced by
Accessing related_to on the interface Cake\Datasource\EntityInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
345
        }
346 2
        $conditions = array(array('OR' => $conditions));
347 2
        $conditions[] = array('Reports.id !=' => $this->id);
348
349 2
        return $conditions;
350
    }
351
}
352