| 
									
										
										
										
											2019-10-26 14:42:51 +02:00
										 |  |  | <?php | 
					
						
							| 
									
										
										
										
											2020-06-30 19:05:35 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-26 14:42:51 +02:00
										 |  |  | /** | 
					
						
							|  |  |  |  * UpdateRequest.php | 
					
						
							| 
									
										
										
										
											2020-06-30 19:05:35 +02:00
										 |  |  |  * Copyright (c) 2020 james@firefly-iii.org | 
					
						
							| 
									
										
										
										
											2019-10-26 14:42:51 +02:00
										 |  |  |  * | 
					
						
							|  |  |  |  * This file is part of Firefly III (https://github.com/firefly-iii). | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  |  * it under the terms of the GNU Affero General Public License as | 
					
						
							|  |  |  |  * published by the Free Software Foundation, either version 3 of the | 
					
						
							|  |  |  |  * License, or (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU Affero General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU Affero General Public License | 
					
						
							|  |  |  |  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-30 19:05:35 +02:00
										 |  |  | declare(strict_types=1); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-26 14:42:51 +02:00
										 |  |  | namespace FireflyIII\Services\FireflyIIIOrg\Update; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 10:39:37 +01:00
										 |  |  | use Carbon\Carbon; | 
					
						
							| 
									
										
										
										
											2022-09-24 11:41:07 +02:00
										 |  |  | use FireflyIII\Events\NewVersionAvailable; | 
					
						
							| 
									
										
										
										
											2019-10-26 14:42:51 +02:00
										 |  |  | use GuzzleHttp\Client; | 
					
						
							|  |  |  | use GuzzleHttp\Exception\GuzzleException; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Class UpdateRequest | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | class UpdateRequest implements UpdateRequestInterface | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-02-02 10:39:37 +01:00
										 |  |  |     public function getUpdateInformation(string $channel): array | 
					
						
							| 
									
										
										
										
											2019-10-26 14:42:51 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-10-29 06:33:43 +01:00
										 |  |  |         app('log')->debug(sprintf('Now in getUpdateInformation(%s)', $channel)); | 
					
						
							| 
									
										
										
										
											2020-02-02 10:39:37 +01:00
										 |  |  |         $information = [ | 
					
						
							|  |  |  |             'level'   => 'error', | 
					
						
							| 
									
										
										
										
											2022-12-29 19:42:26 +01:00
										 |  |  |             'message' => (string)trans('firefly.unknown_error'), | 
					
						
							| 
									
										
										
										
											2020-02-02 10:39:37 +01:00
										 |  |  |         ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // try get array from update server:
 | 
					
						
							|  |  |  |         $updateInfo = $this->contactServer($channel); | 
					
						
							|  |  |  |         if ('error' === $updateInfo['level']) { | 
					
						
							| 
									
										
										
										
											2023-10-29 06:32:00 +01:00
										 |  |  |             app('log')->error('Update information contains an error.'); | 
					
						
							|  |  |  |             app('log')->error($updateInfo['message']); | 
					
						
							| 
									
										
										
										
											2020-02-02 10:39:37 +01:00
										 |  |  |             $information['message'] = $updateInfo['message']; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return $information; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // if no error, parse the result and return
 | 
					
						
							|  |  |  |         return $this->parseResult($updateInfo); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-21 09:15:40 +01:00
										 |  |  |     private function contactServer(string $channel): array | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-10-29 06:33:43 +01:00
										 |  |  |         app('log')->debug(sprintf('Now in contactServer(%s)', $channel)); | 
					
						
							| 
									
										
										
										
											2021-03-21 09:15:40 +01:00
										 |  |  |         // always fall back to current version:
 | 
					
						
							|  |  |  |         $return = [ | 
					
						
							|  |  |  |             'version' => config('firefly.version'), | 
					
						
							| 
									
										
										
										
											2023-02-11 07:36:45 +01:00
										 |  |  |             'date'    => today(config('app.timezone'))->startOfDay(), | 
					
						
							| 
									
										
										
										
											2021-03-21 09:15:40 +01:00
										 |  |  |             'level'   => 'error', | 
					
						
							| 
									
										
										
										
											2022-12-29 19:42:26 +01:00
										 |  |  |             'message' => (string)trans('firefly.unknown_error'), | 
					
						
							| 
									
										
										
										
											2021-03-21 09:15:40 +01:00
										 |  |  |         ]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-12 18:19:30 +02:00
										 |  |  |         $url = config('firefly.update_endpoint'); | 
					
						
							| 
									
										
										
										
											2023-10-29 06:33:43 +01:00
										 |  |  |         app('log')->debug(sprintf('Going to call %s', $url)); | 
					
						
							| 
									
										
										
										
											2023-12-20 19:35:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-21 09:15:40 +01:00
										 |  |  |         try { | 
					
						
							| 
									
										
										
										
											2022-10-30 14:24:37 +01:00
										 |  |  |             $client  = new Client(); | 
					
						
							| 
									
										
										
										
											2021-03-21 09:15:40 +01:00
										 |  |  |             $options = [ | 
					
						
							|  |  |  |                 'headers' => [ | 
					
						
							|  |  |  |                     'User-Agent' => sprintf('FireflyIII/%s/%s', config('firefly.version'), $channel), | 
					
						
							|  |  |  |                 ], | 
					
						
							|  |  |  |                 'timeout' => 3.1415, | 
					
						
							|  |  |  |             ]; | 
					
						
							| 
									
										
										
										
											2022-04-12 18:19:30 +02:00
										 |  |  |             $res     = $client->request('GET', $url, $options); | 
					
						
							| 
									
										
										
										
											2021-04-06 18:48:02 +02:00
										 |  |  |         } catch (GuzzleException $e) { | 
					
						
							| 
									
										
										
										
											2023-10-29 06:32:00 +01:00
										 |  |  |             app('log')->error('Ran into Guzzle error.'); | 
					
						
							|  |  |  |             app('log')->error($e->getMessage()); | 
					
						
							|  |  |  |             app('log')->error($e->getTraceAsString()); | 
					
						
							| 
									
										
										
										
											2021-03-21 09:15:40 +01:00
										 |  |  |             $return['message'] = sprintf('Guzzle: %s', strip_tags($e->getMessage())); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return $return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (200 !== $res->getStatusCode()) { | 
					
						
							| 
									
										
										
										
											2023-10-29 06:32:00 +01:00
										 |  |  |             app('log')->error(sprintf('Response status from server is %d.', $res->getStatusCode())); | 
					
						
							|  |  |  |             app('log')->error((string)$res->getBody()); | 
					
						
							| 
									
										
										
										
											2021-03-21 09:15:40 +01:00
										 |  |  |             $return['message'] = sprintf('Error: %d', $res->getStatusCode()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return $return; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-12-29 19:42:26 +01:00
										 |  |  |         $body = (string)$res->getBody(); | 
					
						
							| 
									
										
										
										
											2023-12-20 19:35:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-21 09:15:40 +01:00
										 |  |  |         try { | 
					
						
							|  |  |  |             $json = json_decode($body, true, 512, JSON_THROW_ON_ERROR); | 
					
						
							| 
									
										
										
										
											2023-12-20 19:35:52 +01:00
										 |  |  |         } catch (\JsonException $e) { | 
					
						
							| 
									
										
										
										
											2023-10-29 06:32:00 +01:00
										 |  |  |             app('log')->error('Body is not valid JSON'); | 
					
						
							|  |  |  |             app('log')->error($body); | 
					
						
							| 
									
										
										
										
											2021-03-21 09:15:40 +01:00
										 |  |  |             $return['message'] = 'Invalid JSON :('; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return $return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-06 18:48:02 +02:00
										 |  |  |         if (!array_key_exists($channel, $json['firefly_iii'])) { | 
					
						
							| 
									
										
										
										
											2023-10-29 06:32:00 +01:00
										 |  |  |             app('log')->error(sprintf('No valid update channel "%s"', $channel)); | 
					
						
							|  |  |  |             app('log')->error($body); | 
					
						
							| 
									
										
										
										
											2021-03-21 09:15:40 +01:00
										 |  |  |             $return['message'] = sprintf('Unknown update channel "%s" :(', $channel); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // parse response a bit. No message yet.
 | 
					
						
							| 
									
										
										
										
											2023-11-28 05:05:42 +01:00
										 |  |  |         $response = $json['firefly_iii'][$channel]; | 
					
						
							|  |  |  |         $date     = Carbon::createFromFormat('Y-m-d', $response['date']); | 
					
						
							|  |  |  |         if (false === $date) { | 
					
						
							|  |  |  |             $date = today(config('app.timezone')); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-03-21 09:15:40 +01:00
										 |  |  |         $return['version'] = $response['version']; | 
					
						
							|  |  |  |         $return['level']   = 'success'; | 
					
						
							| 
									
										
										
										
											2023-11-28 05:05:42 +01:00
										 |  |  |         $return['date']    = $date->startOfDay(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-29 06:31:27 +01:00
										 |  |  |         app('log')->info('Response from update server', $response); | 
					
						
							| 
									
										
										
										
											2021-03-21 09:15:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return $return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 10:39:37 +01:00
										 |  |  |     private function parseResult(array $information): array | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-10-29 06:33:43 +01:00
										 |  |  |         app('log')->debug('Now in parseResult()', $information); | 
					
						
							| 
									
										
										
										
											2020-02-02 10:39:37 +01:00
										 |  |  |         $return  = [ | 
					
						
							|  |  |  |             'level'   => 'error', | 
					
						
							| 
									
										
										
										
											2022-12-29 19:42:26 +01:00
										 |  |  |             'message' => (string)trans('firefly.unknown_error'), | 
					
						
							| 
									
										
										
										
											2020-02-02 10:39:37 +01:00
										 |  |  |         ]; | 
					
						
							|  |  |  |         $current = config('firefly.version'); | 
					
						
							|  |  |  |         $latest  = $information['version']; | 
					
						
							| 
									
										
										
										
											2023-03-04 07:18:20 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // strip the 'v' from the version if it's there.
 | 
					
						
							|  |  |  |         if (str_starts_with($latest, 'v')) { | 
					
						
							|  |  |  |             $latest = substr($latest, 1); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 10:39:37 +01:00
										 |  |  |         $compare = version_compare($latest, $current); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-29 06:33:43 +01:00
										 |  |  |         app('log')->debug(sprintf('Current version is "%s", latest is "%s", result is: %d', $current, $latest, $compare)); | 
					
						
							| 
									
										
										
										
											2020-02-02 10:39:37 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // -1: you're running a newer version:
 | 
					
						
							|  |  |  |         if (-1 === $compare) { | 
					
						
							|  |  |  |             $return['level']   = 'info'; | 
					
						
							| 
									
										
										
										
											2022-12-29 19:42:26 +01:00
										 |  |  |             $return['message'] = (string)trans('firefly.update_newer_version_alert', ['your_version' => $current, 'new_version' => $latest]); | 
					
						
							| 
									
										
										
										
											2023-10-29 06:33:43 +01:00
										 |  |  |             app('log')->debug('User is running a newer version', $return); | 
					
						
							| 
									
										
										
										
											2020-02-02 10:39:37 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             return $return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         // running the current version:
 | 
					
						
							|  |  |  |         if (0 === $compare) { | 
					
						
							|  |  |  |             $return['level']   = 'info'; | 
					
						
							| 
									
										
										
										
											2022-12-29 19:42:26 +01:00
										 |  |  |             $return['message'] = (string)trans('firefly.update_current_version_alert', ['version' => $current]); | 
					
						
							| 
									
										
										
										
											2023-10-29 06:33:43 +01:00
										 |  |  |             app('log')->debug('User is the current version.', $return); | 
					
						
							| 
									
										
										
										
											2020-02-02 10:39:37 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             return $return; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-09-24 11:41:07 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 10:39:37 +01:00
										 |  |  |         // a newer version is available!
 | 
					
						
							|  |  |  |         /** @var Carbon $released */ | 
					
						
							|  |  |  |         $released     = $information['date']; | 
					
						
							| 
									
										
										
										
											2023-02-11 07:36:45 +01:00
										 |  |  |         $today        = today(config('app.timezone'))->startOfDay(); | 
					
						
							| 
									
										
										
										
											2020-02-02 10:39:37 +01:00
										 |  |  |         $diff         = $today->diffInDays($released); | 
					
						
							|  |  |  |         $expectedDiff = config('firefly.update_minimum_age') ?? 6; | 
					
						
							|  |  |  |         // it's still very fresh, and user wants a stable release:
 | 
					
						
							|  |  |  |         if ($diff <= $expectedDiff) { | 
					
						
							|  |  |  |             $return['level']   = 'info'; | 
					
						
							| 
									
										
										
										
											2022-12-29 19:42:26 +01:00
										 |  |  |             $return['message'] = (string)trans( | 
					
						
							| 
									
										
										
										
											2020-02-02 10:39:37 +01:00
										 |  |  |                 'firefly.just_new_release', | 
					
						
							| 
									
										
										
										
											2022-12-29 19:42:26 +01:00
										 |  |  |                 [ | 
					
						
							|  |  |  |                     'version' => $latest, | 
					
						
							|  |  |  |                     'date'    => $released->isoFormat((string)trans('config.month_and_day_js')), | 
					
						
							|  |  |  |                     'days'    => $expectedDiff, | 
					
						
							| 
									
										
										
										
											2020-02-02 10:39:37 +01:00
										 |  |  |                 ] | 
					
						
							|  |  |  |             ); | 
					
						
							| 
									
										
										
										
											2023-10-29 06:33:43 +01:00
										 |  |  |             app('log')->debug('Release is very fresh.', $return); | 
					
						
							| 
									
										
										
										
											2020-02-02 10:39:37 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             return $return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-24 11:41:07 +02:00
										 |  |  |         // it's been around for a while:
 | 
					
						
							| 
									
										
										
										
											2020-02-02 10:39:37 +01:00
										 |  |  |         $return['level']   = 'success'; | 
					
						
							| 
									
										
										
										
											2022-12-29 19:42:26 +01:00
										 |  |  |         $return['message'] = (string)trans( | 
					
						
							| 
									
										
										
										
											2020-02-02 10:39:37 +01:00
										 |  |  |             'firefly.update_new_version_alert', | 
					
						
							|  |  |  |             [ | 
					
						
							|  |  |  |                 'your_version' => $current, | 
					
						
							|  |  |  |                 'new_version'  => $latest, | 
					
						
							| 
									
										
										
										
											2022-12-29 19:42:26 +01:00
										 |  |  |                 'date'         => $released->isoFormat((string)trans('config.month_and_day_js')), | 
					
						
							|  |  |  |             ] | 
					
						
							| 
									
										
										
										
											2020-02-02 10:39:37 +01:00
										 |  |  |         ); | 
					
						
							| 
									
										
										
										
											2023-10-29 06:33:43 +01:00
										 |  |  |         app('log')->debug('New release is old enough.'); | 
					
						
							| 
									
										
										
										
											2020-02-02 10:39:37 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // add warning in case of alpha or beta:
 | 
					
						
							|  |  |  |         // append warning if beta or alpha.
 | 
					
						
							|  |  |  |         $isBeta = $information['is_beta'] ?? false; | 
					
						
							|  |  |  |         if (true === $isBeta) { | 
					
						
							|  |  |  |             $return['message'] = sprintf('%s %s', $return['message'], trans('firefly.update_version_beta')); | 
					
						
							| 
									
										
										
										
											2023-10-29 06:33:43 +01:00
										 |  |  |             app('log')->debug('New release is also a beta!'); | 
					
						
							| 
									
										
										
										
											2020-02-02 10:39:37 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $isAlpha = $information['is_alpha'] ?? false; | 
					
						
							|  |  |  |         if (true === $isAlpha) { | 
					
						
							|  |  |  |             $return['message'] = sprintf('%s %s', $return['message'], trans('firefly.update_version_alpha')); | 
					
						
							| 
									
										
										
										
											2023-10-29 06:33:43 +01:00
										 |  |  |             app('log')->debug('New release is also a alpha!'); | 
					
						
							| 
									
										
										
										
											2020-02-02 10:39:37 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-10-29 06:33:43 +01:00
										 |  |  |         app('log')->debug('New release is here!', $return); | 
					
						
							| 
									
										
										
										
											2020-02-02 10:39:37 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-24 11:41:07 +02:00
										 |  |  |         // send event, this may result in a notification.
 | 
					
						
							|  |  |  |         event(new NewVersionAvailable($return['message'])); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 10:39:37 +01:00
										 |  |  |         return $return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-05-30 07:33:06 +02:00
										 |  |  | } |