Completed
Pull Request — master (#115)
by Deven
17:04
created

ReportsController   A

Complexity

Total Complexity 32

Size/Duplication

Total Lines 280
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 9

Test Coverage

Coverage 58.42%

Importance

Changes 8
Bugs 3 Features 2
Metric Value
wmc 32
c 8
b 3
f 2
lcom 1
cbo 9
dl 0
loc 280
ccs 111
cts 190
cp 0.5842
rs 9.6

10 Methods

Rating   Name   Duplication   Size   Complexity  
A index() 0 18 1
B view() 0 34 4
B mark_related_to() 0 22 5
A unmark_related_to() 0 17 3
B change_state() 0 23 4
B mass_action() 0 41 5
A _setSimilarFields() 0 15 2
A data_tables() 0 66 3
A _findArrayList() 0 7 2
A _findAllDataTable() 0 12 3
1
<?php
2
/* vim: set noexpandtab sw=2 ts=2 sts=2: */
3
namespace App\Controller;
4
5
use App\Controller\AppController;
6
use App\Utility\Sanitize;
7
use Cake\Core\Configure;
8
use Cake\Log\Log;
9
use Cake\ORM\Table;
10
use Cake\ORM\TableRegistry;
11
use Cake\Network\Exception\NotFoundException;
12
/**
13
 * Reports controller handling reports creation and rendering
14
 *
15
 * phpMyAdmin Error reporting server
16
 * Copyright (c) phpMyAdmin project (http://www.phpmyadmin.net)
17
 *
18
 * Licensed under The MIT License
19
 * For full copyright and license information, please see the LICENSE.txt
20
 * Redistributions of files must retain the above copyright notice.
21
 *
22
 * @copyright     Copyright (c) phpMyAdmin project (http://www.phpmyadmin.net)
23
 * @package       Server.Controller
24
 * @link          http://www.phpmyadmin.net
25
 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
26
 */
27
28
/**
29
 * Reports controller handling reports modification and rendering
30
 *
31
 * @package       Server.Controller
32
 */
33
class ReportsController extends AppController {
34
35
	public $components = array('RequestHandler', 'OrderSearch');
36
37
	public $helpers = array('Html', 'Form', 'Reports', 'Incidents');
38
	public $uses = array('Incidents', 'Reports', 'Notifications', 'Developers');
39
40 1
	public function index() {
41 1
		$this->Reports->recursive = -1;
42 1
		$this->set('distinct_statuses',
43 1
			$this->_findArrayList($this->Reports->find()->select(['status'])->distinct(['status']),
44 1
			'status')
45 1
		);
46 1
		$this->set('distinct_versions',
47 1
			$this->_findArrayList($this->Reports->find()->select(['pma_version'])->distinct(['pma_version']), 'pma_version')
48 1
		);
49 1
		$this->set('distinct_error_names',
50 1
			$this->_findArrayList($this->Reports->find('all', array(
51 1
				'fields' => array('error_name'),
52 1
				'conditions' => array('error_name !=' => ''),
53 1
			))->distinct(['error_name']), 'error_name')
54 1
		);
55 1
		$this->set('statuses', $this->Reports->status);
56 1
        $this->autoRender = true;
57 1
	}
58
59 1
	public function view($reportId) {
60 1
		if (!$reportId) {
61
			throw new NotFoundException(__('Invalid Report'));
62
		}
63 1
		$report = $this->Reports->findById($reportId)->toArray();
64 1
		if (!$report) {
65 1
			throw new NotFoundException(__('Invalid Report'));
66
		}
67
68 1
		$this->set('report', $report);
69 1
		$this->set('project_name', Configure::read('GithubRepoPath'));
70 1
		$this->Reports->id = $reportId;
71 1
		$this->set('incidents', $this->Reports->getIncidents()->toArray());
72 1
		$this->set('incidents_with_description',
73 1
            $this->Reports->getIncidentsWithDescription());
74 1
		$this->set('incidents_with_stacktrace',
75 1
				$this->Reports->getIncidentsWithDifferentStacktrace());
76 1
		$this->set('related_reports', $this->Reports->getRelatedReports());
77 1
		$this->set('status', $this->Reports->status);
78 1
		$this->_setSimilarFields($reportId);
79
80
		// if there is an unread notification for this report, then mark it as read
81 1
		$current_developer = TableRegistry::get('Developers')->
0 ignored issues
show
Documentation Bug introduced by
The method findById does not exist on object<Cake\ORM\Table>? 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...
82 1
					findById($this->request->session()->read('Developer.id'))->all()->first();
83
		//$current_developer = Sanitize::clean($current_developer);
84 1
		if ($current_developer) {
85 1
			TableRegistry::get('Notifications')->deleteAll(
86 1
				array('developer_id' => $current_developer['Developer']['id'],
87
					'report_id' => $reportId
88 1
				),
89
				false
0 ignored issues
show
Unused Code introduced by
The call to Table::deleteAll() has too many arguments starting with false.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
90 1
			);
91 1
		}
92 1
	}
93
94 1
	public function data_tables() {
95
		$subquery_params = [
96
			'fields' => [
97 1
				'report_id' => 'report_id',
98
				'inci_count' => 'COUNT(id)'
99 1
				],
100
			'group' => 'report_id'
101 1
		];
102 1
		$subquery = TableRegistry::get('incidents')->find('all', $subquery_params);
103
104
		// override automatic aliasing, for proper usage in joins
105
		$aColumns = [
106 1
			'id' => 'id',
107 1
			'error_name' => 'error_name',
108 1
			'error_message' => 'error_message',
109 1
			'pma_version' => 'pma_version',
110 1
			'status' => 'status',
111 1
			'exception_type' => 'exception_type',
112
			'inci_count' => 'inci_count'
113 1
		];
114
115 1
		$searchConditions = $this->OrderSearch->getSearchConditions($aColumns);
116 1
		$orderConditions = $this->OrderSearch->getOrder($aColumns);
117
118
		$params = [
119 1
			'fields' => $aColumns,
120
			'conditions' => [
121 1
					$searchConditions,
122
					'related_to is NULL'
123 1
				],
124 1
			'order' => $orderConditions,
125 1
		];
126
127 1
		$pagedParams = $params;
128 1
		$pagedParams['limit'] = intval($this->request->query('iDisplayLength'));
129 1
		$pagedParams['offset'] = intval($this->request->query('iDisplayStart'));
130
131 1
		$rows = $this->_findAllDataTable(
132 1
			$this->Reports->find('all', $pagedParams)->innerJoin(
133 1
				['incidents' => $subquery], ['incidents.report_id = Reports.id']
134 1
			)
135 1
		);
136
		//$rows = Sanitize::clean($rows);
137 1
		$totalFiltered = $this->Reports->find('all', $params)->count();
138
139
		// change exception_type from boolean values to strings
140 1
		$dispRows = array();
141 1
		foreach($rows as $row) {
142 1
			$row[4] = $this->Reports->status[$row[4]];
143 1
			$row[5] = (intval($row[5]))?('php'):('js');
144
			$input_elem = "<input type='checkbox' name='reports[]' value='"
145 1
				. $row[0]
146 1
				. "'/>";
147 1
			array_unshift($row, $input_elem);
148 1
			array_push($dispRows, $row);
149 1
		}
150
		$response = array(
151 1
			'iTotalRecords' => $this->Reports->find('all')->count(),
152 1
			'iTotalDisplayRecords' => $totalFiltered,
153 1
			'sEcho' => intval($this->request->query('sEcho')),
154
			'aaData' => $dispRows
155 1
		);
156 1
		$this->autoRender = false;
157 1
		$this->response->body(json_encode($response));
158 1
        return $this->response;
159
	}
160
161
	public function mark_related_to($reportId) {
162
		$relatedTo = $this->request->query("related_to");
163
		if (!$reportId
164
			|| !$relatedTo
165
			|| $reportId == $relatedTo
166
		) {
167
			throw new NotFoundException(__('Invalid Report'));
168
		}
169
170
		$report = $this->Reports->get($reportId);
171
		if (!$report) {
172
			throw new NotFoundException(__('Invalid Report'));
173
		}
174
175
		$this->Reports->addToRelatedGroup($report, $relatedTo);
176
177
		$flash_class = "alert alert-success";
178
		$this->Flash->default("This report has been marked the same as #"
0 ignored issues
show
Documentation Bug introduced by
The method default does not exist on object<Cake\Controller\Component\FlashComponent>? 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...
179
				. $relatedTo,
180
				array("params" => array("class" => $flash_class)));
181
		$this->redirect("/reports/view/$reportId");
182
	}
183
184
	public function unmark_related_to($reportId) {
185
		if (!$reportId) {
186
			throw new NotFoundException(__('Invalid Report'));
187
		}
188
189
		$report = $this->Reports->get($reportId);
190
		if (!$report) {
191
			throw new NotFoundException(__('Invalid Report'));
192
		}
193
194
		$this->Reports->removeFromRelatedGroup($report);
195
196
		$flash_class = "alert alert-success";
197
		$this->Flash->default("This report has been marked as different.",
0 ignored issues
show
Documentation Bug introduced by
The method default does not exist on object<Cake\Controller\Component\FlashComponent>? 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...
198
			array("params" => array("class" => $flash_class)));
199
		$this->redirect("/reports/view/$reportId");
200
	}
201
202
	public function change_state($reportId) {
203
		if (!$reportId) {
204
			throw new NotFoundException(__('Invalid Report'));
205
		}
206
207
		$report = $this->Reports->get($reportId);
208
		if (!$report) {
209
			throw new NotFoundException(__('Invalid Report'));
210
		}
211
212
		$state = $this->request->data['state'];
213
		$newState = $this->Reports->status[$state];
214
		if (!$newState) {
215
			throw new NotFoundException(__('Invalid State'));
216
		}
217
        $report->status = $state;
218
		$this->Reports->save($report);
219
220
		$flash_class = "alert alert-success";
221
		$this->Flash->default("The state has been successfully changed.",
0 ignored issues
show
Documentation Bug introduced by
The method default does not exist on object<Cake\Controller\Component\FlashComponent>? 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...
222
			array("params" => array("class" => $flash_class)));
223
		$this->redirect("/reports/view/$reportId");
224
	}
225
226
	/**
227
	 * To carry out mass actions on Reports
228
	 * Currently only to change their statuses.
229
	 * Can be Extended for other mass operations as well.
230
	 * Expects an array of Report Ids as a POST parameter.
231
	 *
232
	 */
233
	public function mass_action()
234
	{
235
		$flash_class = "alert alert-error";
236
		$state = $this->request->data['state'];
237
		$newState = $this->Reports->status[$state];
238
		if (!$newState) {
239
			Log::write(
240
				'error',
241
				'ERRORED: Invalid param "state" in ReportsController::mass_action()',
242
				'alert'
243
			);
244
			$msg = "ERROR: Invalid State!!";
245
		} else if (count($this->request->data['reports']) == 0) {
246
			$msg = "No Reports Selected!! Please Select Reports and try again.";
247
		} else {
248
			$msg = "Status has been changed to '"
249
				. $this->request->data['state']
250
				. "' for selected Reports!";
251
			$flash_class = "alert alert-success";
252
			foreach($this->request->data['reports'] as $report_id)
253
			{
254
				$report = $this->Reports->get($report_id);
255
				if (!$report) {
256
					Log::write(
257
						'error',
258
						'ERRORED: Invalid report_id in ReportsController::mass_action()',
259
						'alert'
260
					);
261
					$msg = "ERROR:Invalid Report ID:" . $report_id;
262
					$flash_class = "alert alert-error";
263
					break;
264
				}
265
                $report->status = $state;
266
				$this->Reports->save($report);
267
			}
268
		}
269
270
		$this->Flash->default($msg,
0 ignored issues
show
Documentation Bug introduced by
The method default does not exist on object<Cake\Controller\Component\FlashComponent>? 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...
271
			array("params" => array("class" => $flash_class)));
272
		$this->redirect("/reports/");
273
	}
274
275
## HELPERS
276 1
	protected function _setSimilarFields($id) {
277 1
		$this->Reports->id = $id;
278
279 1
		$this->set('columns', TableRegistry::get('Incidents')->summarizableFields);
280 1
		$relatedEntries = array();
281
282 1
		foreach (TableRegistry::get('Incidents')->summarizableFields as $field) {
283
			list($entriesWithCount, $totalEntries) =
284 1
					$this->Reports->getRelatedByField($field, 25, true);
285 1
			$relatedEntries[$field] = $entriesWithCount;
286 1
			$this->set("${field}_distinct_count", $totalEntries);
287 1
		}
288
        //error_log(json_encode($relatedEntries));
289
		$this->set("related_entries", $relatedEntries);
290
	}
291
292
    protected function _findArrayList($results, $key) {
293 1
        $output = array();
294 1
		foreach ($results as $row) {
295 1
			$output[] = $row[$key];
296 1
		}
297 1
		return $output;
298
    }
299
300
    protected function _findAllDataTable($results) {
301 1
		$output = array();
302 1
		foreach ($results as $row) {
303 1
			$output_row = array();
304 1
            $row = $row->toArray();
305 1
			foreach ($row as $key => $value) {
306 1
				$output_row[] = $value;
307 1
			}
308 1
			$output[] = $output_row;
309 1
		}
310 1
		return $output;
311
	}
312
}
313