mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2024-12-25 08:21:08 -06:00
232 lines
8.0 KiB
PHP
232 lines
8.0 KiB
PHP
<?php
|
|
|
|
/**
|
|
* UpdateRequest.php
|
|
* Copyright (c) 2020 james@firefly-iii.org
|
|
*
|
|
* 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/>.
|
|
*/
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace FireflyIII\Services\FireflyIIIOrg\Update;
|
|
|
|
use Carbon\Carbon;
|
|
use FireflyIII\Events\NewVersionAvailable;
|
|
use GuzzleHttp\Client;
|
|
use GuzzleHttp\Exception\GuzzleException;
|
|
use Illuminate\Support\Facades\Log;
|
|
use JsonException;
|
|
|
|
/**
|
|
* Class UpdateRequest
|
|
*/
|
|
class UpdateRequest implements UpdateRequestInterface
|
|
{
|
|
/**
|
|
* @param string $channel
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getUpdateInformation(string $channel): array
|
|
{
|
|
Log::debug(sprintf('Now in getUpdateInformation(%s)', $channel));
|
|
$information = [
|
|
'level' => 'error',
|
|
'message' => (string)trans('firefly.unknown_error'),
|
|
];
|
|
|
|
// try get array from update server:
|
|
$updateInfo = $this->contactServer($channel);
|
|
if ('error' === $updateInfo['level']) {
|
|
Log::error('Update information contains an error.');
|
|
Log::error($updateInfo['message']);
|
|
$information['message'] = $updateInfo['message'];
|
|
|
|
return $information;
|
|
}
|
|
|
|
// if no error, parse the result and return
|
|
return $this->parseResult($updateInfo);
|
|
}
|
|
|
|
/**
|
|
* @param string $channel
|
|
*
|
|
* @return array
|
|
*/
|
|
private function contactServer(string $channel): array
|
|
{
|
|
Log::debug(sprintf('Now in contactServer(%s)', $channel));
|
|
// always fall back to current version:
|
|
$return = [
|
|
'version' => config('firefly.version'),
|
|
'date' => today(config('app.timezone'))->startOfDay(),
|
|
'level' => 'error',
|
|
'message' => (string)trans('firefly.unknown_error'),
|
|
];
|
|
|
|
$url = config('firefly.update_endpoint');
|
|
Log::debug(sprintf('Going to call %s', $url));
|
|
try {
|
|
$client = new Client();
|
|
$options = [
|
|
'headers' => [
|
|
'User-Agent' => sprintf('FireflyIII/%s/%s', config('firefly.version'), $channel),
|
|
],
|
|
'timeout' => 3.1415,
|
|
];
|
|
$res = $client->request('GET', $url, $options);
|
|
} catch (GuzzleException $e) {
|
|
Log::error('Ran into Guzzle error.');
|
|
Log::error($e->getMessage());
|
|
Log::error($e->getTraceAsString());
|
|
$return['message'] = sprintf('Guzzle: %s', strip_tags($e->getMessage()));
|
|
|
|
return $return;
|
|
}
|
|
|
|
if (200 !== $res->getStatusCode()) {
|
|
Log::error(sprintf('Response status from server is %d.', $res->getStatusCode()));
|
|
Log::error((string)$res->getBody());
|
|
$return['message'] = sprintf('Error: %d', $res->getStatusCode());
|
|
|
|
return $return;
|
|
}
|
|
$body = (string)$res->getBody();
|
|
try {
|
|
$json = json_decode($body, true, 512, JSON_THROW_ON_ERROR);
|
|
} catch (JsonException $e) {
|
|
Log::error('Body is not valid JSON');
|
|
Log::error($body);
|
|
$return['message'] = 'Invalid JSON :(';
|
|
|
|
return $return;
|
|
}
|
|
|
|
if (!array_key_exists($channel, $json['firefly_iii'])) {
|
|
Log::error(sprintf('No valid update channel "%s"', $channel));
|
|
Log::error($body);
|
|
$return['message'] = sprintf('Unknown update channel "%s" :(', $channel);
|
|
}
|
|
|
|
// parse response a bit. No message yet.
|
|
$response = $json['firefly_iii'][$channel];
|
|
$return['version'] = $response['version'];
|
|
$return['level'] = 'success';
|
|
$return['date'] = Carbon::createFromFormat('Y-m-d', $response['date'])->startOfDay();
|
|
Log::info('Response from update server', $response);
|
|
|
|
return $return;
|
|
}
|
|
|
|
/**
|
|
* @param array $information
|
|
*
|
|
* @return array
|
|
*/
|
|
private function parseResult(array $information): array
|
|
{
|
|
Log::debug('Now in parseResult()', $information);
|
|
$return = [
|
|
'level' => 'error',
|
|
'message' => (string)trans('firefly.unknown_error'),
|
|
];
|
|
$current = config('firefly.version');
|
|
$latest = $information['version'];
|
|
|
|
// strip the 'v' from the version if it's there.
|
|
if (str_starts_with($latest, 'v')) {
|
|
$latest = substr($latest, 1);
|
|
}
|
|
|
|
$compare = version_compare($latest, $current);
|
|
|
|
Log::debug(sprintf('Current version is "%s", latest is "%s", result is: %d', $current, $latest, $compare));
|
|
|
|
// -1: you're running a newer version:
|
|
if (-1 === $compare) {
|
|
$return['level'] = 'info';
|
|
$return['message'] = (string)trans('firefly.update_newer_version_alert', ['your_version' => $current, 'new_version' => $latest]);
|
|
Log::debug('User is running a newer version', $return);
|
|
|
|
return $return;
|
|
}
|
|
// running the current version:
|
|
if (0 === $compare) {
|
|
$return['level'] = 'info';
|
|
$return['message'] = (string)trans('firefly.update_current_version_alert', ['version' => $current]);
|
|
Log::debug('User is the current version.', $return);
|
|
|
|
return $return;
|
|
}
|
|
|
|
// a newer version is available!
|
|
/** @var Carbon $released */
|
|
$released = $information['date'];
|
|
$today = today(config('app.timezone'))->startOfDay();
|
|
$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';
|
|
$return['message'] = (string)trans(
|
|
'firefly.just_new_release',
|
|
[
|
|
'version' => $latest,
|
|
'date' => $released->isoFormat((string)trans('config.month_and_day_js')),
|
|
'days' => $expectedDiff,
|
|
]
|
|
);
|
|
Log::debug('Release is very fresh.', $return);
|
|
|
|
return $return;
|
|
}
|
|
|
|
// it's been around for a while:
|
|
$return['level'] = 'success';
|
|
$return['message'] = (string)trans(
|
|
'firefly.update_new_version_alert',
|
|
[
|
|
'your_version' => $current,
|
|
'new_version' => $latest,
|
|
'date' => $released->isoFormat((string)trans('config.month_and_day_js')),
|
|
]
|
|
);
|
|
Log::debug('New release is old enough.');
|
|
|
|
// 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'));
|
|
Log::debug('New release is also a beta!');
|
|
}
|
|
|
|
$isAlpha = $information['is_alpha'] ?? false;
|
|
if (true === $isAlpha) {
|
|
$return['message'] = sprintf('%s %s', $return['message'], trans('firefly.update_version_alpha'));
|
|
Log::debug('New release is also a alpha!');
|
|
}
|
|
Log::debug('New release is here!', $return);
|
|
|
|
// send event, this may result in a notification.
|
|
event(new NewVersionAvailable($return['message']));
|
|
|
|
return $return;
|
|
}
|
|
}
|