Completed
Push — master ( da17ac...286914 )
by George
03:50
created

SubmitControllerCreate::checkCMSVersion()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 36
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 5.0342

Importance

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