Completed
Push — master ( 0fdab2...b56490 )
by Michael
08:26 queued 05:10
created

SubmitControllerCreate   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 210
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 86.3%

Importance

Changes 6
Bugs 2 Features 1
Metric Value
wmc 22
c 6
b 2
f 1
lcom 1
cbo 5
dl 0
loc 210
ccs 63
cts 73
cp 0.863
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
B execute() 0 66 7
B checkCMSVersion() 0 26 5
A checkDatabaseType() 0 9 2
B checkPHPVersion() 0 20 5
A validateVersionNumber() 0 4 2
1
<?php
2
3
namespace Stats\Controllers;
4
5
use Joomla\Controller\AbstractController;
6
use Stats\Models\StatsModel;
7
8
/**
9
 * Controller for processing submitted statistics data.
10
 *
11
 * @method         \Stats\WebApplication  getApplication()  Get the application object.
12
 * @property-read  \Stats\WebApplication  $app              Application object
13
 *
14
 * @since          1.0
15
 */
16
class SubmitControllerCreate extends AbstractController
17
{
18
	/**
19
	 * Statistics model object.
20
	 *
21
	 * @var    StatsModel
22
	 * @since  1.0
23
	 */
24
	private $model;
25
26
	/**
27
	 * Allowed Database Types.
28
	 *
29
	 * @var    array
30
	 * @since  1.0
31
	 */
32
	private $databaseTypes = [
33
		'mysql',
34
		'mysqli',
35
		'pdomysql',
36
		'postgresql',
37
		'sqlazure',
38
		'sqlsrv',
39
	];
40
41
	/**
42
	 * Constructor.
43
	 *
44
	 * @param   StatsModel  $model  Statistics model object.
45
	 *
46
	 * @since   1.0
47
	 */
48 1
	public function __construct(StatsModel $model)
49
	{
50 1
		$this->model = $model;
51 1
	}
52
53
	/**
54
	 * Execute the controller.
55
	 *
56
	 * @return  boolean
57
	 *
58
	 * @since   1.0
59
	 */
60 3
	public function execute()
61
	{
62 3
		$input = $this->getInput();
63
64
		$data = [
65 3
			'php_version' => $input->getRaw('php_version'),
66 3
			'db_version'  => $input->getRaw('db_version'),
67 3
			'cms_version' => $input->getRaw('cms_version'),
68 3
			'unique_id'   => $input->getString('unique_id'),
69 3
			'db_type'     => $input->getString('db_type'),
70 3
			'server_os'   => $input->getString('server_os'),
71 3
		];
72
73
		// Backup the original POST before manipulating/validating data
74 3
		$originalData = $data;
75
76
		// Validate the submitted data
77 3
		$data['php_version'] = $this->checkPHPVersion($data['php_version']);
78 3
		$data['cms_version'] = $this->checkCMSVersion($data['cms_version']);
79 3
		$data['db_type']     = $this->checkDatabaseType($data['db_type']);
80 3
		$data['db_version']  = $this->validateVersionNumber($data['db_version']);
81
82
		// We require at a minimum a unique ID and the CMS version
83 3
		if (empty($data['unique_id']) || empty($data['cms_version']))
84 3
		{
85 2
			$this->getApplication()->getLogger()->info(
86 2
				'Missing required data from request.',
87 2
				['postData' => $originalData]
88 2
			);
89
90
			$response = [
91 2
				'error'   => true,
92 2
				'message' => 'There was an error storing the data.',
93 2
			];
94
95 2
			$this->getApplication()->setHeader('HTTP/1.1 500 Internal Server Error', 500, true);
96 2
			$this->getApplication()->setBody(json_encode($response));
97
	
98 2
			return true;
99
		}
100
101
		// If the below data does not pass tests, we do not accept the POST
102 1
		if ($data['php_version'] === false || $data['cms_version'] === false || $data['db_type'] === false || $data['db_version'] === false)
103 1
		{
104
			$response = [
105
				'error'   => true,
106
				'message' => 'Invalid data submission.',
107
			];
108
	
109
			$this->getApplication()->setHeader('HTTP/1.1 500 Internal Server Error', 500, true);
110
			$this->getApplication()->setBody(json_encode($response));
111
	
112
			return true;
113
		}
114
115 1
		$this->model->save((object) $data);
116
117
		$response = [
118 1
			'error'   => false,
119 1
			'message' => 'Data saved successfully',
120 1
		];
121
122 1
		$this->getApplication()->setBody(json_encode($response));
123
124 1
		return true;
125
	}
126
127
	/**
128
	 * Check the CMS version.
129
	 *
130
	 * @param   string  $version  The version number to check.
131
	 *
132
	 * @return  string|boolean  The version number on success or boolean false on failure.
133
	 *
134
	 * @since   1.0
135
	 */
136 3
	private function checkCMSVersion($version)
137
	{
138 3
		$version = $this->validateVersionNumber($version);
139
140
		// If the version number is invalid, don't go any further
141 3
		if ($version === false)
142 3
		{
143 1
			return false;
144
		}
145
146
		// Joomla only uses major.minor.patch so everything else is invalid
147 2
		$explodedVersion = explode('.', $version);
148
149 2
		if (count($explodedVersion) > 3)
150 2
		{
151 1
			return false;
152
		}
153
154
		// We are only collecting data for the 3.x series
155 1
		if (version_compare($version, '3.0.0', '<') || version_compare($version, '4.0.0', '>='))
156 1
		{
157
			return false;
158
		}
159
160 1
		return $version;
161
	}
162
163
	/**
164
	 * Check the database type
165
	 *
166
	 * @param   string  $database  The database type to check.
167
	 *
168
	 * @return  string|boolean  The database type on success or boolean false on failure.
169
	 *
170
	 * @since   1.0
171
	 */
172 3
	private function checkDatabaseType($database)
173
	{
174 3
		if (!in_array($database, $this->databaseTypes))
175 3
		{
176
			return false;
177
		}
178
179 3
		return $database;
180
	}
181
182
	/**
183
	 * Check the PHP version
184
	 *
185
	 * @param   string  $version  The version number to check.
186
	 *
187
	 * @return  string|boolean  The version number on success or boolean false on failure.
188
	 *
189
	 * @since   1.0
190
	 */
191 3
	private function checkPHPVersion($version)
192
	{
193 3
		$version = $this->validateVersionNumber($version);
194
195
		// If the version number is invalid, don't go any further
196 3
		if ($version === false)
197 3
		{
198
			return false;
199
		}
200
201 3
		$majorVersion = substr($version, 0, 1);
202
203
		// The version string should meet the minimum supported PHP version for 3.0.0 and be a released PHP version
204 3
		if (version_compare($version, '5.3.1', '<') || version_compare($version, '8.0.0', '>=') || $majorVersion == 6)
205 3
		{
206
			return false;
207
		}
208
209 3
		return $version;
210
	}
211
212
	/**
213
	 * Validates and filters the version number
214
	 *
215
	 * @param   string  $version  The version string to validate.
216
	 *
217
	 * @return  string|boolean  A validated version number on success or boolean false.
218
	 *
219
	 * @since   1.0
220
	 */
221 3
	private function validateVersionNumber($version)
222
	{
223 3
		return preg_match('/\d+(?:\.\d+)+/', $version, $matches) ? $matches[0] : false;
224
	}
225
}
226