Completed
Push — mysql_improvements ( 7b45c6...94ce4a )
by George
02:24
created

StatsJsonView::render()   C

Complexity

Conditions 9
Paths 7

Size

Total Lines 60
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 17.6098

Importance

Changes 15
Bugs 1 Features 0
Metric Value
c 15
b 1
f 0
dl 0
loc 60
ccs 20
cts 38
cp 0.5263
rs 6.8358
cc 9
eloc 30
nc 7
nop 0
crap 17.6098

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Stats\Views\Stats;
4
5
use Joomla\View\BaseJsonView;
6
7
/**
8
 * JSON response for requesting the stats data.
9
 *
10
 * @property-read  \Stats\Models\StatsModel  $model  The model object.
11
 *
12
 * @since          1.0
13
 */
14
class StatsJsonView extends BaseJsonView
15
{
16
	/**
17
	 * Flag if the response should return the raw data.
18
	 *
19
	 * @var    boolean
20
	 * @since  1.0
21
	 */
22
	private $authorizedRaw = false;
23
24
	/**
25
	 * Array holding the valid data sources.
26
	 *
27
	 * @var    array
28
	 * @since  1.0
29
	 */
30
	private $dataSources = ['php_version', 'db_type', 'db_version', 'cms_version', 'server_os'];
31
32
	/**
33
	 * The data source to return.
34
	 *
35
	 * @var    string
36
	 * @since  1.0
37
	 */
38
	private $source;
39
40
	/**
41
	 * Count of the number of items.
42
	 *
43
	 * @var    integer
44
	 * @since  1.0
45
	 */
46
	private $totalItems = 0;
47
48
	/**
49
	 * Set whether the raw data should be returned.
50
	 *
51
	 * @param   boolean  $authorizedRaw  Flag if the response should return the raw data.
52
	 *
53
	 * @return  void
54
	 *
55
	 * @since   1.0
56
	 */
57 1
	public function isAuthorizedRaw($authorizedRaw)
58
	{
59 1
		$this->authorizedRaw = $authorizedRaw;
60 1
	}
61
62
	/**
63
	 * Method to render the view.
64
	 *
65
	 * @return  string  The rendered view.
66
	 *
67
	 * @since   1.0
68
	 * @throws  \InvalidArgumentException
69
	 */
70 4
	public function render()
71
	{
72 4
		$items = $this->model->getItems($this->source);
73
74
		// Null out the model now to free some memory
75 4
		$this->model = null;
76
77 4
		if ($this->source)
78 4
		{
79 2
			return $this->processSingleSource($items);
80
		}
81
82 2
		$php_version = [];
83 2
		$db_type     = [];
84 2
		$db_version  = [];
85 2
		$cms_version = [];
86 2
		$server_os   = [];
87
88
		// If we have the entire database, we have to loop within each group to put it all together
89 2
		foreach ($items as $group)
90
		{
91 2
			$this->totalItems = 0;
92 2
			foreach ($group as $item)
93
			{
94 2
				foreach ($this->dataSources as $source)
95
				{
96 2
					if (isset($item[$source]) && !is_null($item[$source]))
97 2
					{
98
						// Special case, if the server is empty then change the key to "unknown"
99 2
						if ($source === 'server_os' && empty(trim($item[$source])))
100 2
						{
101
							$item[$source] = 'unknown';
102
						}
103
104 2
						${$source}[$item[$source]] = $item['count'];
105
106
						$this->totalItems += $item['count'];
107
					}
108
				}
109
			}
110
		}
111
112
		unset($items);
113
114
		$data = [
115
			'php_version' => $php_version,
116
			'db_type'     => $db_type,
117
			'db_version'  => $db_version,
118
			'cms_version' => $cms_version,
119
			'server_os'   => $server_os,
120
		];
121
122
		$responseData = $this->buildResponseData($data);
123
124
		$responseData['total'] = $this->totalItems;
125
126
		$this->addData('data', $responseData);
127
128
		return parent::render();
129
	}
130
131
	/**
132
	 * Set the data source.
133
	 *
134
	 * @param   string  $source  Data source to return.
135
	 *
136
	 * @return  void
137
	 *
138
	 * @since   1.0
139
	 */
140 1
	public function setSource($source)
141
	{
142 1
		$this->source = $source;
143 1
	}
144
145
	/**
146
	 * Process the raw data into the response data format.
147
	 *
148
	 * @param   array  $data  The raw data array.
149
	 *
150
	 * @return  array
151
	 *
152
	 * @since   1.0
153
	 */
154 2
	private function buildResponseData(array $data)
155
	{
156 2
		$responseData = [];
157
158 2
		foreach ($data as $key => $value)
159
		{
160 2
			foreach ($value as $name => $count)
161
			{
162
				if ($name)
163 2
				{
164 2
					$responseData[$key][] = [
165 2
						'name'  => $name,
166
						'count' => $count
167 2
					];
168 2
				}
169 2
			}
170 2
		}
171
172 2
		unset($data);
173
174 2
		if (!$this->authorizedRaw)
175 2
		{
176 2
			$responseData = $this->sanitizeData($responseData);
177 2
		}
178
179 2
		return $responseData;
180
	}
181
182
	/**
183
	 * Process the response for a single data source.
184
	 *
185
	 * @param   array  $items  The source items to process.
186
	 *
187
	 * @return  string  The rendered view.
188
	 *
189
	 * @since   1.0
190
	 */
191 2
	private function processSingleSource(array $items)
192
	{
193
		$data = [
194 2
			${$this->source} = [],
195 2
		];
196
197 2
		$this->totalItems = 0;
198
199 2
		foreach ($items as $item)
200
		{
201
			// Special case, if the server is empty then change the key to "unknown"
202 2
			if ($this->source === 'server_os' && empty(trim($item[$this->source])))
203 2
			{
204 1
				$item[$this->source] = 'unknown';
205 1
			}
206
207 2
			$data[$this->source][$item[$this->source]] = $item['count'];
208 2
			$this->totalItems += $item['count'];
209 2
		}
210
211 2
		$responseData = $this->buildResponseData($data);
212
213 2
		$responseData['total'] = $this->totalItems;
214
215 2
		$this->addData('data', $responseData);
216
217 2
		return parent::render();
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (render() instead of processSingleSource()). Are you sure this is correct? If so, you might want to change this to $this->render().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
218
	}
219
220
	/**
221
	 * Sanitize the response data into summarized groups.
222
	 *
223
	 * @param   array  $responseData  The response data to sanitize.
224
	 *
225
	 * @return  array
226
	 *
227
	 * @since   1.0
228
	 */
229 2
	private function sanitizeData(array $responseData)
230
	{
231 2
		foreach ($responseData as $key => $dataGroup)
232
		{
233
			switch ($key)
234
			{
235 2
				case 'php_version':
236 2
				case 'db_version':
237
					// We're going to group by minor version branch here and convert to a percentage
238 1
					$counts = [];
239
240 1
					foreach ($dataGroup as $row)
241
					{
242 1
						$exploded = explode('.', $row['name']);
243 1
						$version  = $exploded[0] . '.' . (isset($exploded[1]) ? $exploded[1] : '0');
244
245
						// If the container does not exist, add it
246 1
						if (!isset($counts[$version]))
247 1
						{
248 1
							$counts[$version] = 0;
249 1
						}
250
251 1
						$counts[$version] += $row['count'];
252 1
					}
253
254 1
					$sanitizedData = [];
255
256 1 View Code Duplication
					foreach ($counts as $version => $count)
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...
257
					{
258 1
						$sanitizedData[$version] = round(($count / $this->totalItems) * 100, 2);
259 1
					}
260
261 1
					$responseData[$key] = $sanitizedData;
262
263 1
					break;
264
265 1
				case 'server_os':
266
					// We're going to group by operating system here
267 1
					$counts = [];
268
269 1
					foreach ($dataGroup as $row)
270
					{
271 1
						$fullOs = explode(' ', $row['name']);
272 1
						$os     = $fullOs[0];
273
274
						// If the container does not exist, add it
275 1
						if (!isset($counts[$os]))
276 1
						{
277 1
							$counts[$os] = 0;
278 1
						}
279
280 1
						$counts[$os] += $row['count'];
281 1
					}
282
283 1
					$sanitizedData = [];
284
285 1 View Code Duplication
					foreach ($counts as $os => $count)
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...
286
					{
287 1
						$sanitizedData[$os] = round(($count / $this->totalItems) * 100, 2);
288 1
					}
289
290 1
					$responseData[$key] = $sanitizedData;
291
292 1
					break;
293
294
				case 'db_type':
295
				case 'cms_version':
296
				default:
297
					// For now, group by the object name and figure out the percentages
298
					$sanitizedData = [];
299
300
					foreach ($dataGroup as $row)
301
					{
302
						$sanitizedData[$row['name']] = round(($row['count'] / $this->totalItems) * 100, 2);
303
					}
304
305
					$responseData[$key] = $sanitizedData;
306
307
					break;
308
			}
309 2
		}
310
311 2
		return $responseData;
312
	}
313
}
314