Completed
Push — master ( c855ce...73f67a )
by
unknown
25:31 queued 15:31
created
src/EventListener/ErrorSubscriber.php 1 patch
Indentation   +123 added lines, -123 removed lines patch added patch discarded remove patch
@@ -27,127 +27,127 @@
 block discarded – undo
27 27
  */
28 28
 class ErrorSubscriber implements SubscriberInterface, LoggerAwareInterface
29 29
 {
30
-    use LoggerAwareTrait;
31
-
32
-    /**
33
-     * Returns an array of events this subscriber will listen to.
34
-     *
35
-     * @return  array
36
-     */
37
-    public static function getSubscribedEvents(): array
38
-    {
39
-        return [
40
-            ApplicationEvents::ERROR         => 'handleWebError',
41
-            ConsoleEvents::APPLICATION_ERROR => 'handleConsoleError',
42
-        ];
43
-    }
44
-
45
-    /**
46
-     * Handle console application errors.
47
-     *
48
-     * @param   ConsoleApplicationErrorEvent  $event  Event object
49
-     *
50
-     * @return  void
51
-     */
52
-    public function handleConsoleError(ConsoleApplicationErrorEvent $event): void
53
-    {
54
-        $this->logger->error(
55
-            sprintf('Uncaught Throwable of type %s caught.', \get_class($event->getError())),
56
-            ['exception' => $event->getError()]
57
-        );
58
-
59
-        (new SymfonyStyle($event->getApplication()->getConsoleInput(), $event->getApplication()->getConsoleOutput()))
60
-            ->error(sprintf('Uncaught Throwable of type %s caught: %s', \get_class($event->getError()), $event->getError()->getMessage()));
61
-    }
62
-
63
-    /**
64
-     * Handle web application errors.
65
-     *
66
-     * @param   ApplicationErrorEvent  $event  Event object
67
-     *
68
-     * @return  void
69
-     */
70
-    public function handleWebError(ApplicationErrorEvent $event): void
71
-    {
72
-        $app = $event->getApplication();
73
-
74
-        switch (true) {
75
-            case $event->getError() instanceof MethodNotAllowedException:
76
-                // Log the error for reference
77
-                $this->logger->error(
78
-                    sprintf('Route `%s` not supported by method `%s`', $app->get('uri.route'), $app->getInput()->getMethod()),
79
-                    ['exception' => $event->getError()]
80
-                );
81
-
82
-                $this->prepareResponse($event);
83
-
84
-                $app->setHeader('Allow', implode(', ', $event->getError()->getAllowedMethods()));
85
-
86
-                break;
87
-
88
-            case $event->getError() instanceof RouteNotFoundException:
89
-                // Log the error for reference
90
-                $this->logger->error(
91
-                    sprintf('Route `%s` not found', $app->get('uri.route')),
92
-                    ['exception' => $event->getError()]
93
-                );
94
-
95
-                $this->prepareResponse($event);
96
-
97
-                break;
98
-
99
-            default:
100
-                $this->logger->error(
101
-                    sprintf('Uncaught Throwable of type %s caught.', \get_class($event->getError())),
102
-                    ['exception' => $event->getError()]
103
-                );
104
-
105
-                $this->prepareResponse($event);
106
-
107
-                break;
108
-        }
109
-    }
110
-
111
-    /**
112
-     * Prepare the response for the event
113
-     *
114
-     * @param   ApplicationErrorEvent  $event  Event object
115
-     *
116
-     * @return  void
117
-     */
118
-    private function prepareResponse(ApplicationErrorEvent $event): void
119
-    {
120
-        /** @var WebApplication $app */
121
-        $app = $event->getApplication();
122
-
123
-        $app->allowCache(false);
124
-
125
-        $data = [
126
-            'code'    => $event->getError()->getCode(),
127
-            'message' => $event->getError()->getMessage(),
128
-            'error'   => true,
129
-        ];
130
-
131
-        $response = new JsonResponse($data);
132
-
133
-        switch ($event->getError()->getCode()) {
134
-            case 404:
135
-                $response = $response->withStatus(404);
136
-
137
-                break;
138
-
139
-            case 405:
140
-                $response = $response->withStatus(405);
141
-
142
-                break;
143
-
144
-            case 500:
145
-            default:
146
-                $response = $response->withStatus(500);
147
-
148
-                break;
149
-        }
150
-
151
-        $app->setResponse($response);
152
-    }
30
+	use LoggerAwareTrait;
31
+
32
+	/**
33
+	 * Returns an array of events this subscriber will listen to.
34
+	 *
35
+	 * @return  array
36
+	 */
37
+	public static function getSubscribedEvents(): array
38
+	{
39
+		return [
40
+			ApplicationEvents::ERROR         => 'handleWebError',
41
+			ConsoleEvents::APPLICATION_ERROR => 'handleConsoleError',
42
+		];
43
+	}
44
+
45
+	/**
46
+	 * Handle console application errors.
47
+	 *
48
+	 * @param   ConsoleApplicationErrorEvent  $event  Event object
49
+	 *
50
+	 * @return  void
51
+	 */
52
+	public function handleConsoleError(ConsoleApplicationErrorEvent $event): void
53
+	{
54
+		$this->logger->error(
55
+			sprintf('Uncaught Throwable of type %s caught.', \get_class($event->getError())),
56
+			['exception' => $event->getError()]
57
+		);
58
+
59
+		(new SymfonyStyle($event->getApplication()->getConsoleInput(), $event->getApplication()->getConsoleOutput()))
60
+			->error(sprintf('Uncaught Throwable of type %s caught: %s', \get_class($event->getError()), $event->getError()->getMessage()));
61
+	}
62
+
63
+	/**
64
+	 * Handle web application errors.
65
+	 *
66
+	 * @param   ApplicationErrorEvent  $event  Event object
67
+	 *
68
+	 * @return  void
69
+	 */
70
+	public function handleWebError(ApplicationErrorEvent $event): void
71
+	{
72
+		$app = $event->getApplication();
73
+
74
+		switch (true) {
75
+			case $event->getError() instanceof MethodNotAllowedException:
76
+				// Log the error for reference
77
+				$this->logger->error(
78
+					sprintf('Route `%s` not supported by method `%s`', $app->get('uri.route'), $app->getInput()->getMethod()),
79
+					['exception' => $event->getError()]
80
+				);
81
+
82
+				$this->prepareResponse($event);
83
+
84
+				$app->setHeader('Allow', implode(', ', $event->getError()->getAllowedMethods()));
85
+
86
+				break;
87
+
88
+			case $event->getError() instanceof RouteNotFoundException:
89
+				// Log the error for reference
90
+				$this->logger->error(
91
+					sprintf('Route `%s` not found', $app->get('uri.route')),
92
+					['exception' => $event->getError()]
93
+				);
94
+
95
+				$this->prepareResponse($event);
96
+
97
+				break;
98
+
99
+			default:
100
+				$this->logger->error(
101
+					sprintf('Uncaught Throwable of type %s caught.', \get_class($event->getError())),
102
+					['exception' => $event->getError()]
103
+				);
104
+
105
+				$this->prepareResponse($event);
106
+
107
+				break;
108
+		}
109
+	}
110
+
111
+	/**
112
+	 * Prepare the response for the event
113
+	 *
114
+	 * @param   ApplicationErrorEvent  $event  Event object
115
+	 *
116
+	 * @return  void
117
+	 */
118
+	private function prepareResponse(ApplicationErrorEvent $event): void
119
+	{
120
+		/** @var WebApplication $app */
121
+		$app = $event->getApplication();
122
+
123
+		$app->allowCache(false);
124
+
125
+		$data = [
126
+			'code'    => $event->getError()->getCode(),
127
+			'message' => $event->getError()->getMessage(),
128
+			'error'   => true,
129
+		];
130
+
131
+		$response = new JsonResponse($data);
132
+
133
+		switch ($event->getError()->getCode()) {
134
+			case 404:
135
+				$response = $response->withStatus(404);
136
+
137
+				break;
138
+
139
+			case 405:
140
+				$response = $response->withStatus(405);
141
+
142
+				break;
143
+
144
+			case 500:
145
+			default:
146
+				$response = $response->withStatus(500);
147
+
148
+				break;
149
+		}
150
+
151
+		$app->setResponse($response);
152
+	}
153 153
 }
Please login to merge, or discard this patch.
src/EventListener/AnalyticsSubscriber.php 1 patch
Indentation   +65 added lines, -65 removed lines patch added patch discarded remove patch
@@ -23,77 +23,77 @@
 block discarded – undo
23 23
  */
24 24
 class AnalyticsSubscriber implements SubscriberInterface, LoggerAwareInterface
25 25
 {
26
-    use LoggerAwareTrait;
26
+	use LoggerAwareTrait;
27 27
 
28
-    /**
29
-     * Application analytics object.
30
-     *
31
-     * @var  Analytics
32
-     */
33
-    private $analytics;
28
+	/**
29
+	 * Application analytics object.
30
+	 *
31
+	 * @var  Analytics
32
+	 */
33
+	private $analytics;
34 34
 
35
-    /**
36
-     * Constructor.
37
-     *
38
-     * @param   Analytics  $analytics  Application analytics object.
39
-     */
40
-    public function __construct(Analytics $analytics)
41
-    {
42
-        $this->analytics = $analytics;
43
-    }
35
+	/**
36
+	 * Constructor.
37
+	 *
38
+	 * @param   Analytics  $analytics  Application analytics object.
39
+	 */
40
+	public function __construct(Analytics $analytics)
41
+	{
42
+		$this->analytics = $analytics;
43
+	}
44 44
 
45
-    /**
46
-     * Returns an array of events this subscriber will listen to.
47
-     *
48
-     * @return  array
49
-     */
50
-    public static function getSubscribedEvents(): array
51
-    {
52
-        return [
53
-            ApplicationEvents::BEFORE_EXECUTE => 'onBeforeExecute',
54
-        ];
55
-    }
45
+	/**
46
+	 * Returns an array of events this subscriber will listen to.
47
+	 *
48
+	 * @return  array
49
+	 */
50
+	public static function getSubscribedEvents(): array
51
+	{
52
+		return [
53
+			ApplicationEvents::BEFORE_EXECUTE => 'onBeforeExecute',
54
+		];
55
+	}
56 56
 
57
-    /**
58
-     * Logs the visit to analytics if able.
59
-     *
60
-     * @param   ApplicationEvent  $event  Event object
61
-     *
62
-     * @return  void
63
-     */
64
-    public function onBeforeExecute(ApplicationEvent $event): void
65
-    {
66
-        $app = $event->getApplication();
57
+	/**
58
+	 * Logs the visit to analytics if able.
59
+	 *
60
+	 * @param   ApplicationEvent  $event  Event object
61
+	 *
62
+	 * @return  void
63
+	 */
64
+	public function onBeforeExecute(ApplicationEvent $event): void
65
+	{
66
+		$app = $event->getApplication();
67 67
 
68
-        if (!($app instanceof WebApplicationInterface)) {
69
-            return;
70
-        }
68
+		if (!($app instanceof WebApplicationInterface)) {
69
+			return;
70
+		}
71 71
 
72
-        // On a GET request to the live domain, submit analytics data
73
-        if (
74
-            $app->getInput()->getMethod() !== 'GET'
75
-            || strpos($app->getInput()->server->getString('HTTP_HOST', ''), 'developer.joomla.org') !== 0
76
-        ) {
77
-            return;
78
-        }
72
+		// On a GET request to the live domain, submit analytics data
73
+		if (
74
+			$app->getInput()->getMethod() !== 'GET'
75
+			|| strpos($app->getInput()->server->getString('HTTP_HOST', ''), 'developer.joomla.org') !== 0
76
+		) {
77
+			return;
78
+		}
79 79
 
80
-        $this->analytics->setAsyncRequest(true)
81
-            ->setProtocolVersion('1')
82
-            ->setTrackingId('UA-544070-16')
83
-            ->setClientId(Uuid::uuid4()->toString())
84
-            ->setDocumentPath($app->get('uri.base.path'))
85
-            ->setIpOverride($app->getInput()->server->getString('REMOTE_ADDR', '127.0.0.1'))
86
-            ->setUserAgentOverride($app->getInput()->server->getString('HTTP_USER_AGENT', 'JoomlaStats/1.0'));
80
+		$this->analytics->setAsyncRequest(true)
81
+			->setProtocolVersion('1')
82
+			->setTrackingId('UA-544070-16')
83
+			->setClientId(Uuid::uuid4()->toString())
84
+			->setDocumentPath($app->get('uri.base.path'))
85
+			->setIpOverride($app->getInput()->server->getString('REMOTE_ADDR', '127.0.0.1'))
86
+			->setUserAgentOverride($app->getInput()->server->getString('HTTP_USER_AGENT', 'JoomlaStats/1.0'));
87 87
 
88
-        // Don't allow sending Analytics data to cause a failure
89
-        try {
90
-            $this->analytics->sendPageview();
91
-        } catch (\Exception $e) {
92
-            // Log the error for reference
93
-            $this->logger->error(
94
-                'Error sending analytics data.',
95
-                ['exception' => $e]
96
-            );
97
-        }
98
-    }
88
+		// Don't allow sending Analytics data to cause a failure
89
+		try {
90
+			$this->analytics->sendPageview();
91
+		} catch (\Exception $e) {
92
+			// Log the error for reference
93
+			$this->logger->error(
94
+				'Error sending analytics data.',
95
+				['exception' => $e]
96
+			);
97
+		}
98
+	}
99 99
 }
Please login to merge, or discard this patch.
src/Controllers/DisplayStatisticsController.php 1 patch
Indentation   +34 added lines, -34 removed lines patch added patch discarded remove patch
@@ -20,45 +20,45 @@
 block discarded – undo
20 20
  */
21 21
 class DisplayStatisticsController extends AbstractController
22 22
 {
23
-    /**
24
-     * JSON view for displaying the statistics.
25
-     *
26
-     * @var  StatsJsonView
27
-     */
28
-    private $view;
23
+	/**
24
+	 * JSON view for displaying the statistics.
25
+	 *
26
+	 * @var  StatsJsonView
27
+	 */
28
+	private $view;
29 29
 
30
-    /**
31
-     * Constructor.
32
-     *
33
-     * @param   StatsJsonView  $view  JSON view for displaying the statistics.
34
-     */
35
-    public function __construct(StatsJsonView $view)
36
-    {
37
-        $this->view = $view;
38
-    }
30
+	/**
31
+	 * Constructor.
32
+	 *
33
+	 * @param   StatsJsonView  $view  JSON view for displaying the statistics.
34
+	 */
35
+	public function __construct(StatsJsonView $view)
36
+	{
37
+		$this->view = $view;
38
+	}
39 39
 
40
-    /**
41
-     * Execute the controller.
42
-     *
43
-     * @return  boolean
44
-     */
45
-    public function execute()
46
-    {
47
-        // Check if we are allowed to receive the raw data
48
-        $authorizedRaw = $this->getInput()->server->getString('HTTP_JOOMLA_RAW', 'fail') === $this->getApplication()->get('stats.rawdata', false);
40
+	/**
41
+	 * Execute the controller.
42
+	 *
43
+	 * @return  boolean
44
+	 */
45
+	public function execute()
46
+	{
47
+		// Check if we are allowed to receive the raw data
48
+		$authorizedRaw = $this->getInput()->server->getString('HTTP_JOOMLA_RAW', 'fail') === $this->getApplication()->get('stats.rawdata', false);
49 49
 
50
-        // Check if a single data source is requested
51
-        $source = $this->getInput()->getString('source', '');
50
+		// Check if a single data source is requested
51
+		$source = $this->getInput()->getString('source', '');
52 52
 
53
-        // Check if a timeframe is requested
54
-        $timeframe = (int) $this->getInput()->getInt('timeframe', 0);
53
+		// Check if a timeframe is requested
54
+		$timeframe = (int) $this->getInput()->getInt('timeframe', 0);
55 55
 
56
-        $this->view->isAuthorizedRaw($authorizedRaw);
57
-        $this->view->setSource($source);
58
-        $this->view->setTimeframe($timeframe);
56
+		$this->view->isAuthorizedRaw($authorizedRaw);
57
+		$this->view->setSource($source);
58
+		$this->view->setTimeframe($timeframe);
59 59
 
60
-        $this->getApplication()->setBody($this->view->render());
60
+		$this->getApplication()->setBody($this->view->render());
61 61
 
62
-        return true;
63
-    }
62
+		return true;
63
+	}
64 64
 }
Please login to merge, or discard this patch.
src/Controllers/SubmitDataController.php 1 patch
Indentation   +233 added lines, -233 removed lines patch added patch discarded remove patch
@@ -25,237 +25,237 @@
 block discarded – undo
25 25
  */
26 26
 class SubmitDataController extends AbstractController
27 27
 {
28
-    use ValidateVersion;
29
-
30
-    /**
31
-     * Statistics repository.
32
-     *
33
-     * @var  StatisticsRepository
34
-     */
35
-    private $repository;
36
-
37
-    /**
38
-     * Influxdb repository.
39
-     *
40
-     * @var  InfluxdbRepository
41
-     */
42
-    private $influxdbRepository;
43
-
44
-    /**
45
-     * Filesystem adapter for the snapshots space.
46
-     *
47
-     * @var  Filesystem
48
-     */
49
-    private $filesystem;
50
-
51
-    /**
52
-     * Allowed Database Types.
53
-     *
54
-     * @var  array
55
-     */
56
-    private $databaseTypes = [
57
-        'mysql',
58
-        'mysqli',
59
-        'pgsql',
60
-        'pdomysql',
61
-        'postgresql',
62
-        'sqlazure',
63
-        'sqlsrv',
64
-    ];
65
-
66
-    /**
67
-     * Constructor.
68
-     *
69
-     * @param   StatisticsRepository  $repository  Statistics repository.
70
-     * @param   Filesystem            $filesystem  Filesystem adapter for the versions space.
71
-     */
72
-    public function __construct(StatisticsRepository $repository, Filesystem $filesystem, InfluxdbRepository $influxdbRepository = null)
73
-    {
74
-        $this->repository         = $repository;
75
-        $this->filesystem         = $filesystem;
76
-        $this->influxdbRepository = $influxdbRepository;
77
-    }
78
-
79
-    /**
80
-     * Execute the controller.
81
-     *
82
-     * @return  boolean
83
-     */
84
-    public function execute()
85
-    {
86
-        $input = $this->getInput();
87
-
88
-        $data = [
89
-            'php_version' => $input->getRaw('php_version', ''),
90
-            'db_version'  => $input->getRaw('db_version', ''),
91
-            'cms_version' => $input->getRaw('cms_version', ''),
92
-            'unique_id'   => $input->getString('unique_id'),
93
-            'db_type'     => $input->getString('db_type', ''),
94
-            'server_os'   => $input->getString('server_os'),
95
-        ];
96
-
97
-        // Backup the original POST before manipulating/validating data
98
-        $originalData = $data;
99
-
100
-        // Validate the submitted data
101
-        $data['php_version'] = $this->checkPHPVersion($data['php_version']);
102
-        $data['cms_version'] = $this->checkCMSVersion($data['cms_version']);
103
-        $data['db_type']     = $this->checkDatabaseType($data['db_type']);
104
-        $data['db_version']  = $this->validateVersionNumber($data['db_version']);
105
-
106
-        // We require at a minimum a unique ID and the CMS version
107
-        if (empty($data['unique_id']) || (empty($data['cms_version']) && $data['cms_version'] !== false)) {
108
-            $this->getApplication()->getLogger()->info(
109
-                'Missing required data from request.',
110
-                ['postData' => $originalData]
111
-            );
112
-
113
-            /** @var JsonResponse $response */
114
-            $response = $this->getApplication()->getResponse();
115
-            $response = $response->withPayload(
116
-                [
117
-                    'error'   => true,
118
-                    'message' => 'There was an error storing the data.',
119
-                ]
120
-            );
121
-            $response = $response->withStatus(500);
122
-
123
-            $this->getApplication()->setResponse($response);
124
-
125
-            return true;
126
-        }
127
-
128
-        // If the below data does not pass tests, we do not accept the POST
129
-        if ($data['php_version'] === false || $data['cms_version'] === false || $data['db_type'] === false || $data['db_version'] === false) {
130
-            /** @var JsonResponse $response */
131
-            $response = $this->getApplication()->getResponse();
132
-            $response = $response->withPayload(
133
-                [
134
-                    'error'   => true,
135
-                    'message' => 'Invalid data submission.',
136
-                ]
137
-            );
138
-            $response = $response->withStatus(500);
139
-
140
-            $this->getApplication()->setResponse($response);
141
-
142
-            return true;
143
-        }
144
-
145
-        // Account for configuration differences with 4.0
146
-        if (version_compare($data['cms_version'], '4.0', 'ge')) {
147
-            // For 4.0 and later, we map `mysql` to the `pdomysql` option to correctly track the database type
148
-            if ($data['db_type'] === 'mysql') {
149
-                $data['db_type'] = 'pdomysql';
150
-            }
151
-        }
152
-
153
-        $this->repository->save((object) $data);
154
-        if ($this->influxdbRepository instanceof InfluxdbRepository) {
155
-            $this->influxdbRepository->save((object) $data);
156
-        }
157
-
158
-        /** @var JsonResponse $response */
159
-        $response = $this->getApplication()->getResponse();
160
-        $response = $response->withPayload(
161
-            [
162
-                'error'   => false,
163
-                'message' => 'Data saved successfully',
164
-            ]
165
-        );
166
-
167
-        $this->getApplication()->setResponse($response);
168
-
169
-        return true;
170
-    }
171
-
172
-    /**
173
-     * Check the CMS version.
174
-     *
175
-     * @param   string  $version  The version number to check.
176
-     *
177
-     * @return  string|boolean  The version number on success or boolean false on failure.
178
-     */
179
-    private function checkCMSVersion(string $version)
180
-    {
181
-        $version = $this->validateVersionNumber($version);
182
-
183
-        // If the version number is invalid, don't go any further
184
-        if ($version === false) {
185
-            return false;
186
-        }
187
-
188
-        // Joomla only uses major.minor.patch so everything else is invalid
189
-        $explodedVersion = explode('.', $version);
190
-
191
-        if (\count($explodedVersion) > 3) {
192
-            return false;
193
-        }
194
-
195
-        try {
196
-            $validVersions = json_decode($this->filesystem->read('joomla.json'), true);
197
-        } catch (FileNotFoundException $exception) {
198
-            throw new \RuntimeException('Missing Joomla! release listing', 500, $exception);
199
-        }
200
-
201
-        // Check that the version is in our valid release list
202
-        if (!\in_array($version, $validVersions)) {
203
-            return false;
204
-        }
205
-
206
-        return $version;
207
-    }
208
-
209
-    /**
210
-     * Check the database type
211
-     *
212
-     * @param   string  $database  The database type to check.
213
-     *
214
-     * @return  string|boolean  The database type on success or boolean false on failure.
215
-     */
216
-    private function checkDatabaseType(string $database)
217
-    {
218
-        if (!\in_array($database, $this->databaseTypes)) {
219
-            return false;
220
-        }
221
-
222
-        return $database;
223
-    }
224
-
225
-    /**
226
-     * Check the PHP version
227
-     *
228
-     * @param   string  $version  The version number to check.
229
-     *
230
-     * @return  string|boolean  The version number on success or boolean false on failure.
231
-     */
232
-    private function checkPHPVersion(string $version)
233
-    {
234
-        $version = $this->validateVersionNumber($version);
235
-
236
-        // If the version number is invalid, don't go any further
237
-        if ($version === false) {
238
-            return false;
239
-        }
240
-
241
-        // We only track versions based on major.minor.patch so everything else is invalid
242
-        $explodedVersion = explode('.', $version);
243
-
244
-        if (\count($explodedVersion) > 3) {
245
-            return false;
246
-        }
247
-
248
-        try {
249
-            $validVersions = json_decode($this->filesystem->read('php.json'), true);
250
-        } catch (FileNotFoundException $exception) {
251
-            throw new \RuntimeException('Missing PHP release listing', 500, $exception);
252
-        }
253
-
254
-        // Check that the version is in our valid release list
255
-        if (!\in_array($version, $validVersions)) {
256
-            return false;
257
-        }
258
-
259
-        return $version;
260
-    }
28
+	use ValidateVersion;
29
+
30
+	/**
31
+	 * Statistics repository.
32
+	 *
33
+	 * @var  StatisticsRepository
34
+	 */
35
+	private $repository;
36
+
37
+	/**
38
+	 * Influxdb repository.
39
+	 *
40
+	 * @var  InfluxdbRepository
41
+	 */
42
+	private $influxdbRepository;
43
+
44
+	/**
45
+	 * Filesystem adapter for the snapshots space.
46
+	 *
47
+	 * @var  Filesystem
48
+	 */
49
+	private $filesystem;
50
+
51
+	/**
52
+	 * Allowed Database Types.
53
+	 *
54
+	 * @var  array
55
+	 */
56
+	private $databaseTypes = [
57
+		'mysql',
58
+		'mysqli',
59
+		'pgsql',
60
+		'pdomysql',
61
+		'postgresql',
62
+		'sqlazure',
63
+		'sqlsrv',
64
+	];
65
+
66
+	/**
67
+	 * Constructor.
68
+	 *
69
+	 * @param   StatisticsRepository  $repository  Statistics repository.
70
+	 * @param   Filesystem            $filesystem  Filesystem adapter for the versions space.
71
+	 */
72
+	public function __construct(StatisticsRepository $repository, Filesystem $filesystem, InfluxdbRepository $influxdbRepository = null)
73
+	{
74
+		$this->repository         = $repository;
75
+		$this->filesystem         = $filesystem;
76
+		$this->influxdbRepository = $influxdbRepository;
77
+	}
78
+
79
+	/**
80
+	 * Execute the controller.
81
+	 *
82
+	 * @return  boolean
83
+	 */
84
+	public function execute()
85
+	{
86
+		$input = $this->getInput();
87
+
88
+		$data = [
89
+			'php_version' => $input->getRaw('php_version', ''),
90
+			'db_version'  => $input->getRaw('db_version', ''),
91
+			'cms_version' => $input->getRaw('cms_version', ''),
92
+			'unique_id'   => $input->getString('unique_id'),
93
+			'db_type'     => $input->getString('db_type', ''),
94
+			'server_os'   => $input->getString('server_os'),
95
+		];
96
+
97
+		// Backup the original POST before manipulating/validating data
98
+		$originalData = $data;
99
+
100
+		// Validate the submitted data
101
+		$data['php_version'] = $this->checkPHPVersion($data['php_version']);
102
+		$data['cms_version'] = $this->checkCMSVersion($data['cms_version']);
103
+		$data['db_type']     = $this->checkDatabaseType($data['db_type']);
104
+		$data['db_version']  = $this->validateVersionNumber($data['db_version']);
105
+
106
+		// We require at a minimum a unique ID and the CMS version
107
+		if (empty($data['unique_id']) || (empty($data['cms_version']) && $data['cms_version'] !== false)) {
108
+			$this->getApplication()->getLogger()->info(
109
+				'Missing required data from request.',
110
+				['postData' => $originalData]
111
+			);
112
+
113
+			/** @var JsonResponse $response */
114
+			$response = $this->getApplication()->getResponse();
115
+			$response = $response->withPayload(
116
+				[
117
+					'error'   => true,
118
+					'message' => 'There was an error storing the data.',
119
+				]
120
+			);
121
+			$response = $response->withStatus(500);
122
+
123
+			$this->getApplication()->setResponse($response);
124
+
125
+			return true;
126
+		}
127
+
128
+		// If the below data does not pass tests, we do not accept the POST
129
+		if ($data['php_version'] === false || $data['cms_version'] === false || $data['db_type'] === false || $data['db_version'] === false) {
130
+			/** @var JsonResponse $response */
131
+			$response = $this->getApplication()->getResponse();
132
+			$response = $response->withPayload(
133
+				[
134
+					'error'   => true,
135
+					'message' => 'Invalid data submission.',
136
+				]
137
+			);
138
+			$response = $response->withStatus(500);
139
+
140
+			$this->getApplication()->setResponse($response);
141
+
142
+			return true;
143
+		}
144
+
145
+		// Account for configuration differences with 4.0
146
+		if (version_compare($data['cms_version'], '4.0', 'ge')) {
147
+			// For 4.0 and later, we map `mysql` to the `pdomysql` option to correctly track the database type
148
+			if ($data['db_type'] === 'mysql') {
149
+				$data['db_type'] = 'pdomysql';
150
+			}
151
+		}
152
+
153
+		$this->repository->save((object) $data);
154
+		if ($this->influxdbRepository instanceof InfluxdbRepository) {
155
+			$this->influxdbRepository->save((object) $data);
156
+		}
157
+
158
+		/** @var JsonResponse $response */
159
+		$response = $this->getApplication()->getResponse();
160
+		$response = $response->withPayload(
161
+			[
162
+				'error'   => false,
163
+				'message' => 'Data saved successfully',
164
+			]
165
+		);
166
+
167
+		$this->getApplication()->setResponse($response);
168
+
169
+		return true;
170
+	}
171
+
172
+	/**
173
+	 * Check the CMS version.
174
+	 *
175
+	 * @param   string  $version  The version number to check.
176
+	 *
177
+	 * @return  string|boolean  The version number on success or boolean false on failure.
178
+	 */
179
+	private function checkCMSVersion(string $version)
180
+	{
181
+		$version = $this->validateVersionNumber($version);
182
+
183
+		// If the version number is invalid, don't go any further
184
+		if ($version === false) {
185
+			return false;
186
+		}
187
+
188
+		// Joomla only uses major.minor.patch so everything else is invalid
189
+		$explodedVersion = explode('.', $version);
190
+
191
+		if (\count($explodedVersion) > 3) {
192
+			return false;
193
+		}
194
+
195
+		try {
196
+			$validVersions = json_decode($this->filesystem->read('joomla.json'), true);
197
+		} catch (FileNotFoundException $exception) {
198
+			throw new \RuntimeException('Missing Joomla! release listing', 500, $exception);
199
+		}
200
+
201
+		// Check that the version is in our valid release list
202
+		if (!\in_array($version, $validVersions)) {
203
+			return false;
204
+		}
205
+
206
+		return $version;
207
+	}
208
+
209
+	/**
210
+	 * Check the database type
211
+	 *
212
+	 * @param   string  $database  The database type to check.
213
+	 *
214
+	 * @return  string|boolean  The database type on success or boolean false on failure.
215
+	 */
216
+	private function checkDatabaseType(string $database)
217
+	{
218
+		if (!\in_array($database, $this->databaseTypes)) {
219
+			return false;
220
+		}
221
+
222
+		return $database;
223
+	}
224
+
225
+	/**
226
+	 * Check the PHP version
227
+	 *
228
+	 * @param   string  $version  The version number to check.
229
+	 *
230
+	 * @return  string|boolean  The version number on success or boolean false on failure.
231
+	 */
232
+	private function checkPHPVersion(string $version)
233
+	{
234
+		$version = $this->validateVersionNumber($version);
235
+
236
+		// If the version number is invalid, don't go any further
237
+		if ($version === false) {
238
+			return false;
239
+		}
240
+
241
+		// We only track versions based on major.minor.patch so everything else is invalid
242
+		$explodedVersion = explode('.', $version);
243
+
244
+		if (\count($explodedVersion) > 3) {
245
+			return false;
246
+		}
247
+
248
+		try {
249
+			$validVersions = json_decode($this->filesystem->read('php.json'), true);
250
+		} catch (FileNotFoundException $exception) {
251
+			throw new \RuntimeException('Missing PHP release listing', 500, $exception);
252
+		}
253
+
254
+		// Check that the version is in our valid release list
255
+		if (!\in_array($version, $validVersions)) {
256
+			return false;
257
+		}
258
+
259
+		return $version;
260
+	}
261 261
 }
Please login to merge, or discard this patch.
src/Decorators/ValidateVersion.php 1 patch
Indentation   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -14,15 +14,15 @@
 block discarded – undo
14 14
  */
15 15
 trait ValidateVersion
16 16
 {
17
-    /**
18
-     * Validates and filters the version number
19
-     *
20
-     * @param   string  $version  The version string to validate.
21
-     *
22
-     * @return  string|boolean  A validated version number on success or boolean false.
23
-     */
24
-    protected function validateVersionNumber(string $version)
25
-    {
26
-        return preg_match('/\d+(?:\.\d+)+/', $version, $matches) ? $matches[0] : false;
27
-    }
17
+	/**
18
+	 * Validates and filters the version number
19
+	 *
20
+	 * @param   string  $version  The version string to validate.
21
+	 *
22
+	 * @return  string|boolean  A validated version number on success or boolean false.
23
+	 */
24
+	protected function validateVersionNumber(string $version)
25
+	{
26
+		return preg_match('/\d+(?:\.\d+)+/', $version, $matches) ? $matches[0] : false;
27
+	}
28 28
 }
Please login to merge, or discard this patch.
src/Commands/UpdateCommand.php 2 patches
Indentation   +69 added lines, -69 removed lines patch added patch discarded remove patch
@@ -22,73 +22,73 @@
 block discarded – undo
22 22
  */
23 23
 class UpdateCommand extends AbstractCommand
24 24
 {
25
-    /**
26
-     * The default command name
27
-     *
28
-     * @var  string|null
29
-     */
30
-    protected static $defaultName = 'update:server';
31
-
32
-    /**
33
-     * Internal function to execute the command.
34
-     *
35
-     * @param   InputInterface   $input   The input to inject into the command.
36
-     * @param   OutputInterface  $output  The output to inject into the command.
37
-     *
38
-     * @return  integer  The command exit code
39
-     */
40
-    protected function doExecute(InputInterface $input, OutputInterface $output): int
41
-    {
42
-        $symfonyStyle = new SymfonyStyle($input, $output);
43
-
44
-        $symfonyStyle->title('Update Server');
45
-        $symfonyStyle->comment('Updating server to git HEAD');
46
-
47
-        if (!$this->getHelperSet()) {
48
-            $symfonyStyle->error('The helper set has not been registered to the update command.');
49
-
50
-            return 1;
51
-        }
52
-
53
-        /** @var ProcessHelper $processHelper */
54
-        $processHelper = $this->getHelperSet()->get('process');
55
-
56
-        // Pull from remote repo
57
-        try {
58
-            $processHelper->mustRun($output, new Process(['git', 'pull'], APPROOT));
59
-        } catch (ProcessFailedException $e) {
60
-            $this->getApplication()->getLogger()->error('Could not execute `git pull`', ['exception' => $e]);
61
-
62
-            $symfonyStyle->error('Error running `git pull`: ' . $e->getMessage());
63
-
64
-            return 1;
65
-        }
66
-
67
-        $symfonyStyle->comment('Updating Composer resources');
68
-
69
-        // Run Composer install
70
-        try {
71
-            $processHelper->mustRun($output, new Process(['composer', 'install', '--no-dev', '-o', '-a'], APPROOT));
72
-        } catch (ProcessFailedException $e) {
73
-            $this->getApplication()->getLogger()->error('Could not update Composer resources', ['exception' => $e]);
74
-
75
-            $symfonyStyle->error('Error updating Composer resources: ' . $e->getMessage());
76
-
77
-            return 1;
78
-        }
79
-
80
-        $symfonyStyle->success('Update complete');
81
-
82
-        return 0;
83
-    }
84
-
85
-    /**
86
-     * Configures the current command.
87
-     *
88
-     * @return  void
89
-     */
90
-    protected function configure(): void
91
-    {
92
-        $this->setDescription('Update the server to the current git HEAD');
93
-    }
25
+	/**
26
+	 * The default command name
27
+	 *
28
+	 * @var  string|null
29
+	 */
30
+	protected static $defaultName = 'update:server';
31
+
32
+	/**
33
+	 * Internal function to execute the command.
34
+	 *
35
+	 * @param   InputInterface   $input   The input to inject into the command.
36
+	 * @param   OutputInterface  $output  The output to inject into the command.
37
+	 *
38
+	 * @return  integer  The command exit code
39
+	 */
40
+	protected function doExecute(InputInterface $input, OutputInterface $output): int
41
+	{
42
+		$symfonyStyle = new SymfonyStyle($input, $output);
43
+
44
+		$symfonyStyle->title('Update Server');
45
+		$symfonyStyle->comment('Updating server to git HEAD');
46
+
47
+		if (!$this->getHelperSet()) {
48
+			$symfonyStyle->error('The helper set has not been registered to the update command.');
49
+
50
+			return 1;
51
+		}
52
+
53
+		/** @var ProcessHelper $processHelper */
54
+		$processHelper = $this->getHelperSet()->get('process');
55
+
56
+		// Pull from remote repo
57
+		try {
58
+			$processHelper->mustRun($output, new Process(['git', 'pull'], APPROOT));
59
+		} catch (ProcessFailedException $e) {
60
+			$this->getApplication()->getLogger()->error('Could not execute `git pull`', ['exception' => $e]);
61
+
62
+			$symfonyStyle->error('Error running `git pull`: ' . $e->getMessage());
63
+
64
+			return 1;
65
+		}
66
+
67
+		$symfonyStyle->comment('Updating Composer resources');
68
+
69
+		// Run Composer install
70
+		try {
71
+			$processHelper->mustRun($output, new Process(['composer', 'install', '--no-dev', '-o', '-a'], APPROOT));
72
+		} catch (ProcessFailedException $e) {
73
+			$this->getApplication()->getLogger()->error('Could not update Composer resources', ['exception' => $e]);
74
+
75
+			$symfonyStyle->error('Error updating Composer resources: ' . $e->getMessage());
76
+
77
+			return 1;
78
+		}
79
+
80
+		$symfonyStyle->success('Update complete');
81
+
82
+		return 0;
83
+	}
84
+
85
+	/**
86
+	 * Configures the current command.
87
+	 *
88
+	 * @return  void
89
+	 */
90
+	protected function configure(): void
91
+	{
92
+		$this->setDescription('Update the server to the current git HEAD');
93
+	}
94 94
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -59,7 +59,7 @@  discard block
 block discarded – undo
59 59
         } catch (ProcessFailedException $e) {
60 60
             $this->getApplication()->getLogger()->error('Could not execute `git pull`', ['exception' => $e]);
61 61
 
62
-            $symfonyStyle->error('Error running `git pull`: ' . $e->getMessage());
62
+            $symfonyStyle->error('Error running `git pull`: '.$e->getMessage());
63 63
 
64 64
             return 1;
65 65
         }
@@ -72,7 +72,7 @@  discard block
 block discarded – undo
72 72
         } catch (ProcessFailedException $e) {
73 73
             $this->getApplication()->getLogger()->error('Could not update Composer resources', ['exception' => $e]);
74 74
 
75
-            $symfonyStyle->error('Error updating Composer resources: ' . $e->getMessage());
75
+            $symfonyStyle->error('Error updating Composer resources: '.$e->getMessage());
76 76
 
77 77
             return 1;
78 78
         }
Please login to merge, or discard this patch.
src/Commands/Tags/FetchJoomlaTagsCommand.php 2 patches
Indentation   +103 added lines, -103 removed lines patch added patch discarded remove patch
@@ -20,107 +20,107 @@
 block discarded – undo
20 20
  */
21 21
 class FetchJoomlaTagsCommand extends AbstractTagCommand
22 22
 {
23
-    use ValidateVersion;
24
-
25
-    /**
26
-     * The default command name
27
-     *
28
-     * @var  string|null
29
-     */
30
-    protected static $defaultName = 'tags:joomla';
31
-
32
-    /**
33
-     * Constructor.
34
-     *
35
-     * @param   GitHub      $github      GitHub API object.
36
-     * @param   Filesystem  $filesystem  Filesystem adapter for the versions space.
37
-     */
38
-    public function __construct(GitHub $github, Filesystem $filesystem)
39
-    {
40
-        parent::__construct($github, $filesystem);
41
-
42
-        $this->repoName  = 'joomla-cms';
43
-        $this->repoOwner = 'joomla';
44
-    }
45
-
46
-    /**
47
-     * Internal function to execute the command.
48
-     *
49
-     * @param   InputInterface   $input   The input to inject into the command.
50
-     * @param   OutputInterface  $output  The output to inject into the command.
51
-     *
52
-     * @return  integer  The command exit code
53
-     */
54
-    protected function doExecute(InputInterface $input, OutputInterface $output): int
55
-    {
56
-        $this->io->title('Fetching Joomla Releases');
57
-
58
-        $versions    = [];
59
-        $highVersion = '0.0.0';
60
-
61
-        foreach ($this->getTags() as $tag) {
62
-            $version = $this->validateVersionNumber($tag->name);
63
-
64
-            // Only process if the tag name looks like a version number
65
-            if ($version === false) {
66
-                continue;
67
-            }
68
-
69
-            // Joomla only uses major.minor.patch so everything else is invalid
70
-            $explodedVersion = explode('.', $version);
71
-
72
-            if (\count($explodedVersion) != 3) {
73
-                continue;
74
-            }
75
-
76
-            // Version collection is valid for the 3.x series and later
77
-            if (version_compare($version, '3.0.0', '<')) {
78
-                continue;
79
-            }
80
-
81
-            // We have a valid version number, great news... add it to our array if it isn't already present
82
-            if (!\in_array($version, $versions)) {
83
-                $versions[] = $version;
84
-
85
-                // If this version is higher than our high version, replace it
86
-                // TODO - When 4.0 is stable adjust this logic
87
-                if (version_compare($version, '4.0', '<') && version_compare($version, $highVersion, '>')) {
88
-                    $highVersion = $version;
89
-                }
90
-            }
91
-        }
92
-
93
-        // If the high version is not the default then let's add some (arbitrary) allowed versions based on the repo's dev structure
94
-        if ($highVersion !== '0.0.0') {
95
-            $explodedVersion = explode('.', $highVersion);
96
-
97
-            // Allow the next patch release after this one
98
-            $nextPatch  = $explodedVersion[2] + 1;
99
-            $versions[] = $explodedVersion[0] . '.' . $explodedVersion[1] . '.' . $nextPatch;
100
-
101
-            // And allow the next minor release after this one
102
-            $nextMinor  = $explodedVersion[1] + 1;
103
-            $versions[] = $explodedVersion[0] . '.' . $nextMinor . '.0';
104
-        }
105
-
106
-        if (!$this->filesystem->put('joomla.json', json_encode($versions))) {
107
-            $this->io->error('Failed writing version data to the filesystem.');
108
-
109
-            return 1;
110
-        }
111
-
112
-        $this->io->success('Joomla! versions updated.');
113
-
114
-        return 0;
115
-    }
116
-
117
-    /**
118
-     * Configures the current command.
119
-     *
120
-     * @return  void
121
-     */
122
-    protected function configure(): void
123
-    {
124
-        $this->setDescription('Parses the release tags for the Joomla! CMS GitHub repository.');
125
-    }
23
+	use ValidateVersion;
24
+
25
+	/**
26
+	 * The default command name
27
+	 *
28
+	 * @var  string|null
29
+	 */
30
+	protected static $defaultName = 'tags:joomla';
31
+
32
+	/**
33
+	 * Constructor.
34
+	 *
35
+	 * @param   GitHub      $github      GitHub API object.
36
+	 * @param   Filesystem  $filesystem  Filesystem adapter for the versions space.
37
+	 */
38
+	public function __construct(GitHub $github, Filesystem $filesystem)
39
+	{
40
+		parent::__construct($github, $filesystem);
41
+
42
+		$this->repoName  = 'joomla-cms';
43
+		$this->repoOwner = 'joomla';
44
+	}
45
+
46
+	/**
47
+	 * Internal function to execute the command.
48
+	 *
49
+	 * @param   InputInterface   $input   The input to inject into the command.
50
+	 * @param   OutputInterface  $output  The output to inject into the command.
51
+	 *
52
+	 * @return  integer  The command exit code
53
+	 */
54
+	protected function doExecute(InputInterface $input, OutputInterface $output): int
55
+	{
56
+		$this->io->title('Fetching Joomla Releases');
57
+
58
+		$versions    = [];
59
+		$highVersion = '0.0.0';
60
+
61
+		foreach ($this->getTags() as $tag) {
62
+			$version = $this->validateVersionNumber($tag->name);
63
+
64
+			// Only process if the tag name looks like a version number
65
+			if ($version === false) {
66
+				continue;
67
+			}
68
+
69
+			// Joomla only uses major.minor.patch so everything else is invalid
70
+			$explodedVersion = explode('.', $version);
71
+
72
+			if (\count($explodedVersion) != 3) {
73
+				continue;
74
+			}
75
+
76
+			// Version collection is valid for the 3.x series and later
77
+			if (version_compare($version, '3.0.0', '<')) {
78
+				continue;
79
+			}
80
+
81
+			// We have a valid version number, great news... add it to our array if it isn't already present
82
+			if (!\in_array($version, $versions)) {
83
+				$versions[] = $version;
84
+
85
+				// If this version is higher than our high version, replace it
86
+				// TODO - When 4.0 is stable adjust this logic
87
+				if (version_compare($version, '4.0', '<') && version_compare($version, $highVersion, '>')) {
88
+					$highVersion = $version;
89
+				}
90
+			}
91
+		}
92
+
93
+		// If the high version is not the default then let's add some (arbitrary) allowed versions based on the repo's dev structure
94
+		if ($highVersion !== '0.0.0') {
95
+			$explodedVersion = explode('.', $highVersion);
96
+
97
+			// Allow the next patch release after this one
98
+			$nextPatch  = $explodedVersion[2] + 1;
99
+			$versions[] = $explodedVersion[0] . '.' . $explodedVersion[1] . '.' . $nextPatch;
100
+
101
+			// And allow the next minor release after this one
102
+			$nextMinor  = $explodedVersion[1] + 1;
103
+			$versions[] = $explodedVersion[0] . '.' . $nextMinor . '.0';
104
+		}
105
+
106
+		if (!$this->filesystem->put('joomla.json', json_encode($versions))) {
107
+			$this->io->error('Failed writing version data to the filesystem.');
108
+
109
+			return 1;
110
+		}
111
+
112
+		$this->io->success('Joomla! versions updated.');
113
+
114
+		return 0;
115
+	}
116
+
117
+	/**
118
+	 * Configures the current command.
119
+	 *
120
+	 * @return  void
121
+	 */
122
+	protected function configure(): void
123
+	{
124
+		$this->setDescription('Parses the release tags for the Joomla! CMS GitHub repository.');
125
+	}
126 126
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -96,11 +96,11 @@
 block discarded – undo
96 96
 
97 97
             // Allow the next patch release after this one
98 98
             $nextPatch  = $explodedVersion[2] + 1;
99
-            $versions[] = $explodedVersion[0] . '.' . $explodedVersion[1] . '.' . $nextPatch;
99
+            $versions[] = $explodedVersion[0].'.'.$explodedVersion[1].'.'.$nextPatch;
100 100
 
101 101
             // And allow the next minor release after this one
102 102
             $nextMinor  = $explodedVersion[1] + 1;
103
-            $versions[] = $explodedVersion[0] . '.' . $nextMinor . '.0';
103
+            $versions[] = $explodedVersion[0].'.'.$nextMinor.'.0';
104 104
         }
105 105
 
106 106
         if (!$this->filesystem->put('joomla.json', json_encode($versions))) {
Please login to merge, or discard this patch.
src/Commands/Tags/FetchPhpTagsCommand.php 2 patches
Indentation   +125 added lines, -125 removed lines patch added patch discarded remove patch
@@ -20,129 +20,129 @@
 block discarded – undo
20 20
  */
21 21
 class FetchPhpTagsCommand extends AbstractTagCommand
22 22
 {
23
-    use ValidateVersion;
24
-
25
-    /**
26
-     * The default command name
27
-     *
28
-     * @var  string|null
29
-     */
30
-    protected static $defaultName = 'tags:php';
31
-
32
-    /**
33
-     * Constructor.
34
-     *
35
-     * @param   GitHub      $github      GitHub API object.
36
-     * @param   Filesystem  $filesystem  Filesystem adapter for the versions space.
37
-     */
38
-    public function __construct(GitHub $github, Filesystem $filesystem)
39
-    {
40
-        parent::__construct($github, $filesystem);
41
-
42
-        $this->repoName  = 'php-src';
43
-        $this->repoOwner = 'php';
44
-    }
45
-
46
-    /**
47
-     * Internal function to execute the command.
48
-     *
49
-     * @param   InputInterface   $input   The input to inject into the command.
50
-     * @param   OutputInterface  $output  The output to inject into the command.
51
-     *
52
-     * @return  integer  The command exit code
53
-     */
54
-    protected function doExecute(InputInterface $input, OutputInterface $output): int
55
-    {
56
-        $this->io->title('Fetching PHP Releases');
57
-
58
-        $versions          = [];
59
-        $supportedBranches = [
60
-            '7.2' => '',
61
-            '7.3' => '',
62
-            '7.4' => '',
63
-        ];
64
-
65
-        foreach ($this->getTags() as $tag) {
66
-            // Replace 'php-' from the tag to get our version number; skip if the segment doesn't exist
67
-            if (strpos($tag->name, 'php-') !== 0) {
68
-                continue;
69
-            }
70
-
71
-            $version = substr($tag->name, 4);
72
-
73
-            $version = $this->validateVersionNumber($version);
74
-
75
-            // Only process if the tag name looks like a version number
76
-            if ($version === false) {
77
-                continue;
78
-            }
79
-
80
-            // We only track versions based on major.minor.patch so everything else is invalid
81
-            $explodedVersion = explode('.', $version);
82
-
83
-            if (\count($explodedVersion) != 3) {
84
-                continue;
85
-            }
86
-
87
-            // Joomla collects stats for the 3.x branch and later, the minimum PHP version for 3.0.0 was 5.3.1
88
-            if (version_compare($version, '5.3.1', '<')) {
89
-                continue;
90
-            }
91
-
92
-            // We have a valid version number, great news... add it to our array if it isn't already present
93
-            if (!\in_array($version, $versions)) {
94
-                $versions[] = $version;
95
-
96
-                // If this version is higher than our branch's high version, replace it
97
-                $branch = substr($version, 0, 3);
98
-
99
-                if (isset($supportedBranches[$branch]) && version_compare($version, $supportedBranches[$branch], '>')) {
100
-                    $supportedBranches[$branch] = $version;
101
-                }
102
-            }
103
-        }
104
-
105
-        // For each supported branch, also add the next patch release
106
-        foreach ($supportedBranches as $branch => $version) {
107
-            $explodedVersion = explode('.', $version);
108
-
109
-            $nextPatch  = $explodedVersion[2] + 1;
110
-            $versions[] = $explodedVersion[0] . '.' . $explodedVersion[1] . '.' . $nextPatch;
111
-        }
112
-
113
-        // Use $branch from the previous loop to allow the next minor version (PHP's master branch)
114
-        $explodedVersion = explode('.', $branch);
115
-
116
-        $nextMinor   = $explodedVersion[1] + 1;
117
-        $nextRelease = $explodedVersion[0] . '.' . $nextMinor . '.0';
118
-
119
-        // There won't be a PHP 7.5, change next release to 8.0 if needed
120
-        if ($nextRelease === '7.5.0') {
121
-            $nextRelease = '8.0.0';
122
-        }
123
-
124
-        if (!\in_array($nextRelease, $versions, true)) {
125
-            $versions[] = $nextRelease;
126
-        }
127
-
128
-        if (!$this->filesystem->put('php.json', json_encode($versions))) {
129
-            $this->io->error('Failed writing version data to the filesystem.');
130
-
131
-            return 1;
132
-        }
133
-
134
-        $this->io->success('PHP versions updated.');
135
-
136
-        return 0;
137
-    }
138
-
139
-    /**
140
-     * Configures the current command.
141
-     *
142
-     * @return  void
143
-     */
144
-    protected function configure(): void
145
-    {
146
-        $this->setDescription('Parses the release tags for the PHP GitHub repository.');
147
-    }
23
+	use ValidateVersion;
24
+
25
+	/**
26
+	 * The default command name
27
+	 *
28
+	 * @var  string|null
29
+	 */
30
+	protected static $defaultName = 'tags:php';
31
+
32
+	/**
33
+	 * Constructor.
34
+	 *
35
+	 * @param   GitHub      $github      GitHub API object.
36
+	 * @param   Filesystem  $filesystem  Filesystem adapter for the versions space.
37
+	 */
38
+	public function __construct(GitHub $github, Filesystem $filesystem)
39
+	{
40
+		parent::__construct($github, $filesystem);
41
+
42
+		$this->repoName  = 'php-src';
43
+		$this->repoOwner = 'php';
44
+	}
45
+
46
+	/**
47
+	 * Internal function to execute the command.
48
+	 *
49
+	 * @param   InputInterface   $input   The input to inject into the command.
50
+	 * @param   OutputInterface  $output  The output to inject into the command.
51
+	 *
52
+	 * @return  integer  The command exit code
53
+	 */
54
+	protected function doExecute(InputInterface $input, OutputInterface $output): int
55
+	{
56
+		$this->io->title('Fetching PHP Releases');
57
+
58
+		$versions          = [];
59
+		$supportedBranches = [
60
+			'7.2' => '',
61
+			'7.3' => '',
62
+			'7.4' => '',
63
+		];
64
+
65
+		foreach ($this->getTags() as $tag) {
66
+			// Replace 'php-' from the tag to get our version number; skip if the segment doesn't exist
67
+			if (strpos($tag->name, 'php-') !== 0) {
68
+				continue;
69
+			}
70
+
71
+			$version = substr($tag->name, 4);
72
+
73
+			$version = $this->validateVersionNumber($version);
74
+
75
+			// Only process if the tag name looks like a version number
76
+			if ($version === false) {
77
+				continue;
78
+			}
79
+
80
+			// We only track versions based on major.minor.patch so everything else is invalid
81
+			$explodedVersion = explode('.', $version);
82
+
83
+			if (\count($explodedVersion) != 3) {
84
+				continue;
85
+			}
86
+
87
+			// Joomla collects stats for the 3.x branch and later, the minimum PHP version for 3.0.0 was 5.3.1
88
+			if (version_compare($version, '5.3.1', '<')) {
89
+				continue;
90
+			}
91
+
92
+			// We have a valid version number, great news... add it to our array if it isn't already present
93
+			if (!\in_array($version, $versions)) {
94
+				$versions[] = $version;
95
+
96
+				// If this version is higher than our branch's high version, replace it
97
+				$branch = substr($version, 0, 3);
98
+
99
+				if (isset($supportedBranches[$branch]) && version_compare($version, $supportedBranches[$branch], '>')) {
100
+					$supportedBranches[$branch] = $version;
101
+				}
102
+			}
103
+		}
104
+
105
+		// For each supported branch, also add the next patch release
106
+		foreach ($supportedBranches as $branch => $version) {
107
+			$explodedVersion = explode('.', $version);
108
+
109
+			$nextPatch  = $explodedVersion[2] + 1;
110
+			$versions[] = $explodedVersion[0] . '.' . $explodedVersion[1] . '.' . $nextPatch;
111
+		}
112
+
113
+		// Use $branch from the previous loop to allow the next minor version (PHP's master branch)
114
+		$explodedVersion = explode('.', $branch);
115
+
116
+		$nextMinor   = $explodedVersion[1] + 1;
117
+		$nextRelease = $explodedVersion[0] . '.' . $nextMinor . '.0';
118
+
119
+		// There won't be a PHP 7.5, change next release to 8.0 if needed
120
+		if ($nextRelease === '7.5.0') {
121
+			$nextRelease = '8.0.0';
122
+		}
123
+
124
+		if (!\in_array($nextRelease, $versions, true)) {
125
+			$versions[] = $nextRelease;
126
+		}
127
+
128
+		if (!$this->filesystem->put('php.json', json_encode($versions))) {
129
+			$this->io->error('Failed writing version data to the filesystem.');
130
+
131
+			return 1;
132
+		}
133
+
134
+		$this->io->success('PHP versions updated.');
135
+
136
+		return 0;
137
+	}
138
+
139
+	/**
140
+	 * Configures the current command.
141
+	 *
142
+	 * @return  void
143
+	 */
144
+	protected function configure(): void
145
+	{
146
+		$this->setDescription('Parses the release tags for the PHP GitHub repository.');
147
+	}
148 148
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -107,14 +107,14 @@
 block discarded – undo
107 107
             $explodedVersion = explode('.', $version);
108 108
 
109 109
             $nextPatch  = $explodedVersion[2] + 1;
110
-            $versions[] = $explodedVersion[0] . '.' . $explodedVersion[1] . '.' . $nextPatch;
110
+            $versions[] = $explodedVersion[0].'.'.$explodedVersion[1].'.'.$nextPatch;
111 111
         }
112 112
 
113 113
         // Use $branch from the previous loop to allow the next minor version (PHP's master branch)
114 114
         $explodedVersion = explode('.', $branch);
115 115
 
116 116
         $nextMinor   = $explodedVersion[1] + 1;
117
-        $nextRelease = $explodedVersion[0] . '.' . $nextMinor . '.0';
117
+        $nextRelease = $explodedVersion[0].'.'.$nextMinor.'.0';
118 118
 
119 119
         // There won't be a PHP 7.5, change next release to 8.0 if needed
120 120
         if ($nextRelease === '7.5.0') {
Please login to merge, or discard this patch.
src/Commands/Tags/AbstractTagCommand.php 1 patch
Indentation   +96 added lines, -96 removed lines patch added patch discarded remove patch
@@ -21,100 +21,100 @@
 block discarded – undo
21 21
  */
22 22
 abstract class AbstractTagCommand extends AbstractCommand
23 23
 {
24
-    /**
25
-     * GitHub API object.
26
-     *
27
-     * @var  GitHub
28
-     */
29
-    protected $github;
30
-
31
-    /**
32
-     * Filesystem adapter for the snapshots space.
33
-     *
34
-     * @var  Filesystem
35
-     */
36
-    protected $filesystem;
37
-
38
-    /**
39
-     * Output helper.
40
-     *
41
-     * @var  SymfonyStyle
42
-     */
43
-    protected $io;
44
-
45
-    /**
46
-     * The GitHub repository to query.
47
-     *
48
-     * @var  string
49
-     */
50
-    protected $repoName;
51
-
52
-    /**
53
-     * The owner of the GitHub repository to query.
54
-     *
55
-     * @var  string
56
-     */
57
-    protected $repoOwner;
58
-
59
-    /**
60
-     * Constructor.
61
-     *
62
-     * @param   GitHub      $github      GitHub API object.
63
-     * @param   Filesystem  $filesystem  Filesystem adapter for the versions space.
64
-     */
65
-    public function __construct(GitHub $github, Filesystem $filesystem)
66
-    {
67
-        $this->github     = $github;
68
-        $this->filesystem = $filesystem;
69
-
70
-        parent::__construct();
71
-    }
72
-
73
-    /**
74
-     * Internal hook to initialise the command after the input has been bound and before the input is validated.
75
-     *
76
-     * @param   InputInterface   $input   The input to inject into the command.
77
-     * @param   OutputInterface  $output  The output to inject into the command.
78
-     *
79
-     * @return  void
80
-     */
81
-    protected function initialise(InputInterface $input, OutputInterface $output): void
82
-    {
83
-        $this->io = new SymfonyStyle($input, $output);
84
-    }
85
-
86
-    /**
87
-     * Get the tags for a repository
88
-     *
89
-     * @return  array
90
-     */
91
-    protected function getTags(): array
92
-    {
93
-        $tags = [];
94
-
95
-        $this->io->comment('Fetching page 1 of tags.');
96
-
97
-        // Get the first page so we can process the headers to figure out how many times we need to do this
98
-        $tags = array_merge($tags, $this->github->repositories->getTags($this->repoOwner, $this->repoName, 1));
99
-
100
-        $response = $this->github->repositories->getApiResponse();
101
-
102
-        if ($response->hasHeader('Link')) {
103
-            preg_match('/(\?page=[0-9]+>; rel=\"last\")/', $response->getHeader('Link')[0], $matches);
104
-
105
-            if ($matches && isset($matches[0])) {
106
-                preg_match('/\d+/', $matches[0], $pages);
107
-
108
-                $lastPage = $pages[0];
109
-
110
-                for ($page = 2; $page <= $lastPage; $page++) {
111
-                    $this->io->comment(sprintf('Fetching page %d of %d pages of tags.', $page, $lastPage));
112
-
113
-                    $tags = array_merge($tags, $this->github->repositories->getTags($this->repoOwner, $this->repoName, $page));
114
-                }
115
-            }
116
-        }
117
-
118
-        return $tags;
119
-    }
24
+	/**
25
+	 * GitHub API object.
26
+	 *
27
+	 * @var  GitHub
28
+	 */
29
+	protected $github;
30
+
31
+	/**
32
+	 * Filesystem adapter for the snapshots space.
33
+	 *
34
+	 * @var  Filesystem
35
+	 */
36
+	protected $filesystem;
37
+
38
+	/**
39
+	 * Output helper.
40
+	 *
41
+	 * @var  SymfonyStyle
42
+	 */
43
+	protected $io;
44
+
45
+	/**
46
+	 * The GitHub repository to query.
47
+	 *
48
+	 * @var  string
49
+	 */
50
+	protected $repoName;
51
+
52
+	/**
53
+	 * The owner of the GitHub repository to query.
54
+	 *
55
+	 * @var  string
56
+	 */
57
+	protected $repoOwner;
58
+
59
+	/**
60
+	 * Constructor.
61
+	 *
62
+	 * @param   GitHub      $github      GitHub API object.
63
+	 * @param   Filesystem  $filesystem  Filesystem adapter for the versions space.
64
+	 */
65
+	public function __construct(GitHub $github, Filesystem $filesystem)
66
+	{
67
+		$this->github     = $github;
68
+		$this->filesystem = $filesystem;
69
+
70
+		parent::__construct();
71
+	}
72
+
73
+	/**
74
+	 * Internal hook to initialise the command after the input has been bound and before the input is validated.
75
+	 *
76
+	 * @param   InputInterface   $input   The input to inject into the command.
77
+	 * @param   OutputInterface  $output  The output to inject into the command.
78
+	 *
79
+	 * @return  void
80
+	 */
81
+	protected function initialise(InputInterface $input, OutputInterface $output): void
82
+	{
83
+		$this->io = new SymfonyStyle($input, $output);
84
+	}
85
+
86
+	/**
87
+	 * Get the tags for a repository
88
+	 *
89
+	 * @return  array
90
+	 */
91
+	protected function getTags(): array
92
+	{
93
+		$tags = [];
94
+
95
+		$this->io->comment('Fetching page 1 of tags.');
96
+
97
+		// Get the first page so we can process the headers to figure out how many times we need to do this
98
+		$tags = array_merge($tags, $this->github->repositories->getTags($this->repoOwner, $this->repoName, 1));
99
+
100
+		$response = $this->github->repositories->getApiResponse();
101
+
102
+		if ($response->hasHeader('Link')) {
103
+			preg_match('/(\?page=[0-9]+>; rel=\"last\")/', $response->getHeader('Link')[0], $matches);
104
+
105
+			if ($matches && isset($matches[0])) {
106
+				preg_match('/\d+/', $matches[0], $pages);
107
+
108
+				$lastPage = $pages[0];
109
+
110
+				for ($page = 2; $page <= $lastPage; $page++) {
111
+					$this->io->comment(sprintf('Fetching page %d of %d pages of tags.', $page, $lastPage));
112
+
113
+					$tags = array_merge($tags, $this->github->repositories->getTags($this->repoOwner, $this->repoName, $page));
114
+				}
115
+			}
116
+		}
117
+
118
+		return $tags;
119
+	}
120 120
 }
Please login to merge, or discard this patch.