Completed
Push — master ( 10f95b...bf15d4 )
by Michael
09:02
created

SubmitControllerCreate::checkCMSVersion()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 36
Code Lines 14

Duplication

Lines 36
Ratio 100 %

Code Coverage

Tests 12
CRAP Score 5.0729

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 36
loc 36
ccs 12
cts 14
cp 0.8571
rs 8.439
cc 5
eloc 14
nc 5
nop 1
crap 5.0729
1
<?php
2
/**
3
 * Joomla! Statistics Server
4
 *
5
 * @copyright  Copyright (C) 2013 - 2017 Open Source Matters, Inc. All rights reserved.
6
 * @license    http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License Version 2 or Later
7
 */
8
9
namespace Joomla\StatsServer\Controllers;
10
11
use Joomla\Controller\AbstractController;
12
use Joomla\StatsServer\Decorators\ValidateVersion;
13
use Joomla\StatsServer\Models\StatsModel;
14
15
/**
16
 * Controller for processing submitted statistics data.
17
 *
18
 * @method         \Joomla\StatsServer\WebApplication  getApplication()  Get the application object.
19
 * @property-read  \Joomla\StatsServer\WebApplication  $app              Application object
20
 *
21
 * @since          1.0
22
 */
23
class SubmitControllerCreate extends AbstractController
24
{
25
	use ValidateVersion;
26
27
	/**
28
	 * Statistics model object.
29
	 *
30
	 * @var    StatsModel
31
	 * @since  1.0
32
	 */
33
	private $model;
34
35
	/**
36
	 * Allowed Database Types.
37
	 *
38
	 * @var    array
39
	 * @since  1.0
40
	 */
41
	private $databaseTypes = [
42
		'mysql',
43
		'mysqli',
44
		'pdomysql',
45
		'postgresql',
46
		'sqlazure',
47
		'sqlsrv',
48
	];
49
50
	/**
51
	 * Constructor.
52
	 *
53
	 * @param   StatsModel  $model  Statistics model object.
54
	 *
55
	 * @since   1.0
56
	 */
57 1
	public function __construct(StatsModel $model)
58
	{
59 1
		$this->model = $model;
60 1
	}
61
62
	/**
63
	 * Execute the controller.
64
	 *
65
	 * @return  boolean
66
	 *
67
	 * @since   1.0
68
	 */
69 3
	public function execute()
70
	{
71 3
		$input = $this->getInput();
72
73
		$data = [
74 3
			'php_version' => $input->getRaw('php_version', ''),
75 3
			'db_version'  => $input->getRaw('db_version', ''),
76 3
			'cms_version' => $input->getRaw('cms_version', ''),
77 3
			'unique_id'   => $input->getString('unique_id'),
78 3
			'db_type'     => $input->getString('db_type', ''),
79 3
			'server_os'   => $input->getString('server_os'),
80
		];
81
82
		// Backup the original POST before manipulating/validating data
83 3
		$originalData = $data;
84
85
		// Validate the submitted data
86 3
		$data['php_version'] = $this->checkPHPVersion($data['php_version']);
87 3
		$data['cms_version'] = $this->checkCMSVersion($data['cms_version']);
88 3
		$data['db_type']     = $this->checkDatabaseType($data['db_type']);
89 3
		$data['db_version']  = $this->validateVersionNumber($data['db_version']);
90
91
		// We require at a minimum a unique ID and the CMS version
92 3
		if (empty($data['unique_id']) || empty($data['cms_version']))
93
		{
94 2
			$this->getApplication()->getLogger()->info(
95 2
				'Missing required data from request.',
96 2
				['postData' => $originalData]
97
			);
98
99
			$response = [
100 2
				'error'   => true,
101
				'message' => 'There was an error storing the data.',
102
			];
103
104 2
			$this->getApplication()->setHeader('HTTP/1.1 500 Internal Server Error', 500, true);
105 2
			$this->getApplication()->setBody(json_encode($response));
106
107 2
			return true;
108
		}
109
110
		// If the below data does not pass tests, we do not accept the POST
111 1
		if ($data['php_version'] === false || $data['cms_version'] === false || $data['db_type'] === false || $data['db_version'] === false)
112
		{
113
			$response = [
114
				'error'   => true,
115
				'message' => 'Invalid data submission.',
116
			];
117
118
			$this->getApplication()->setHeader('HTTP/1.1 500 Internal Server Error', 500, true);
119
			$this->getApplication()->setBody(json_encode($response));
120
121
			return true;
122
		}
123
124 1
		$this->model->save((object) $data);
125
126
		$response = [
127 1
			'error'   => false,
128
			'message' => 'Data saved successfully',
129
		];
130
131 1
		$this->getApplication()->setBody(json_encode($response));
132
133 1
		return true;
134
	}
135
136
	/**
137
	 * Check the CMS version.
138
	 *
139
	 * @param   string  $version  The version number to check.
140
	 *
141
	 * @return  string|boolean  The version number on success or boolean false on failure.
142
	 *
143
	 * @since   1.0
144
	 */
145 3 View Code Duplication
	private function checkCMSVersion(string $version)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
146
	{
147 3
		$version = $this->validateVersionNumber($version);
148
149
		// If the version number is invalid, don't go any further
150 3
		if ($version === false)
151
		{
152 1
			return false;
153
		}
154
155
		// Joomla only uses major.minor.patch so everything else is invalid
156 2
		$explodedVersion = explode('.', $version);
157
158 2
		if (count($explodedVersion) > 3)
159
		{
160 1
			return false;
161
		}
162
163
		// Import the valid release listing
164 1
		$path = APPROOT . '/versions/joomla.json';
165
166 1
		if (!file_exists($path))
167
		{
168
			throw new \RuntimeException('Missing Joomla! release listing', 500);
169
		}
170
171 1
		$validVersions = json_decode(file_get_contents($path), true);
172
173
		// Check that the version is in our valid release list
174 1
		if (!in_array($version, $validVersions))
175
		{
176
			return false;
177
		}
178
179 1
		return $version;
180
	}
181
182
	/**
183
	 * Check the database type
184
	 *
185
	 * @param   string  $database  The database type to check.
186
	 *
187
	 * @return  string|boolean  The database type on success or boolean false on failure.
188
	 *
189
	 * @since   1.0
190
	 */
191 3
	private function checkDatabaseType(string $database)
192
	{
193 3
		if (!in_array($database, $this->databaseTypes))
194
		{
195
			return false;
196
		}
197
198 3
		return $database;
199
	}
200
201
	/**
202
	 * Check the PHP version
203
	 *
204
	 * @param   string  $version  The version number to check.
205
	 *
206
	 * @return  string|boolean  The version number on success or boolean false on failure.
207
	 *
208
	 * @since   1.0
209
	 */
210 3 View Code Duplication
	private function checkPHPVersion(string $version)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
211
	{
212 3
		$version = $this->validateVersionNumber($version);
213
214
		// If the version number is invalid, don't go any further
215 3
		if ($version === false)
216
		{
217
			return false;
218
		}
219
220
		// We only track versions based on major.minor.patch so everything else is invalid
221 3
		$explodedVersion = explode('.', $version);
222
223 3
		if (count($explodedVersion) > 3)
224
		{
225
			return false;
226
		}
227
228
		// Import the valid release listing
229 3
		$path = APPROOT . '/versions/php.json';
230
231 3
		if (!file_exists($path))
232
		{
233
			throw new \RuntimeException('Missing PHP release listing', 500);
234
		}
235
236 3
		$validVersions = json_decode(file_get_contents($path), true);
237
238
		// Check that the version is in our valid release list
239 3
		if (!in_array($version, $validVersions))
240
		{
241
			return false;
242
		}
243
244 3
		return $version;
245
	}
246
}
247