Files
firefly-iii/app/Services/FireflyIIIOrg/Update/UpdateRequest.php

284 lines
10 KiB
PHP
Raw Normal View History

<?php
2020-06-30 19:05:35 +02:00
/**
* UpdateRequest.php
2020-06-30 19:05:35 +02:00
* 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/>.
*/
2020-06-30 19:05:35 +02:00
declare(strict_types=1);
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;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Support\Facades\Log;
/**
* Class UpdateRequest
*/
class UpdateRequest implements UpdateRequestInterface
{
2020-02-02 10:39:37 +01:00
public function getUpdateInformation(string $channel): array
{
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 to get array from update server:
$updateInfo = $this->contactServer($channel);
2020-02-02 10:39:37 +01:00
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 = [
2021-03-21 09:15:40 +01:00
'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
];
$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;
}
$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.
$response = $json['firefly_iii'][$channel];
$date = Carbon::createFromFormat('Y-m-d', $response['date']);
2023-11-28 05:05:42 +01:00
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;
}
2024-02-14 19:47:35 +01:00
/**
* TODO make shorter
*/
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);
2024-02-22 06:52:58 +01:00
$current = (string)config('firefly.version');
$latest = (string)$information['version'];
// strip the 'v' from the version if it's there.
if (str_starts_with($latest, 'v')) {
$latest = substr($latest, 1);
}
if (str_starts_with($current, 'develop')) {
2024-02-22 06:52:58 +01:00
return $this->parseResultDevelop($current, $latest, $information);
}
2024-02-22 06:52:58 +01:00
$compare = version_compare($latest, $current);
2020-02-02 10:39:37 +01:00
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) {
2024-02-22 06:52:58 +01:00
return $this->runsNewerVersion($current, $latest);
2020-02-02 10:39:37 +01:00
}
// running the current version:
if (0 === $compare) {
2024-02-22 06:52:58 +01:00
return $this->runsSameVersion($current);
2020-02-02 10:39:37 +01:00
}
2022-09-24 11:41:07 +02:00
2020-02-02 10:39:37 +01:00
// a newer version is available!
/** @var Carbon $released */
2024-02-22 06:52:58 +01:00
$released = $information['date'];
$today = today(config('app.timezone'))->startOfDay();
$diff = $today->diffInDays($released);
$expectedDiff = config('firefly.update_minimum_age') ?? 6;
$isBeta = $information['is_beta'] ?? false;
$isAlpha = $information['is_alpha'] ?? false;
// it's new but alpha:
if (true === $isAlpha) {
return $this->releasedNewAlpha($current, $latest, $released);
2020-02-02 10:39:37 +01:00
}
if (true === $isBeta) {
2024-02-22 06:52:58 +01:00
return $this->releasedNewBeta($current, $latest, $released);
2020-02-02 10:39:37 +01:00
}
2024-02-22 06:52:58 +01:00
return $this->releasedNewVersion($current, $latest, $released);
2020-02-02 10:39:37 +01:00
}
2024-02-20 20:05:43 +01:00
2024-02-22 06:52:58 +01:00
private function parseResultDevelop(string $current, string $latest, array $information): array
2024-02-20 20:05:43 +01:00
{
Log::debug(sprintf('User is running develop version "%s"', $current));
$parts = explode('/', $current);
$return = [];
2024-02-20 20:05:43 +01:00
/** @var Carbon $devDate */
$devDate = Carbon::createFromFormat('Y-m-d', $parts[1]);
2024-02-20 20:05:43 +01:00
if ($devDate->lte($information['date'])) {
Log::debug(sprintf('This development release is older, release = %s, latest version %s = %s', $devDate->format('Y-m-d'), $latest, $information['date']->format('Y-m-d')));
$return['level'] = 'info';
$return['message'] = (string)trans('firefly.update_current_dev_older', ['version' => $current, 'new_version' => $latest]);
return $return;
}
Log::debug(sprintf('This development release is newer, release = %s, latest version %s = %s', $devDate->format('Y-m-d'), $latest, $information['date']->format('Y-m-d')));
$return['level'] = 'info';
$return['message'] = (string)trans('firefly.update_current_dev_newer', ['version' => $current, 'new_version' => $latest]);
return $return;
}
2024-02-22 06:52:58 +01:00
private function runsNewerVersion(string $current, string $latest): array
{
$return = [
'level' => 'info',
'message' => (string)trans('firefly.update_newer_version_alert', ['your_version' => $current, 'new_version' => $latest]),
];
app('log')->debug('User is running a newer version', $return);
return $return;
}
private function runsSameVersion(string $current)
{
$return = [
'level' => 'info',
'message' => (string)trans('firefly.update_current_version_alert', ['version' => $current]),
];
app('log')->debug('User is the current version.', $return);
return $return;
}
private function releasedNewAlpha(string $current, string $latest, Carbon $date): array
{
app('log')->debug('New release is also a alpha!');
$message = (string)trans(
'firefly.update_new_version_alert',
[
'your_version' => $current,
'new_version' => $latest,
'date' => $date->isoFormat((string)trans('config.month_and_day_js')),
]
);
return [
'level' => 'success',
'message' => sprintf('%s %s', $message, trans('firefly.update_version_alpha')),
];
}
private function releasedNewBeta(string $current, string $latest, Carbon $date): array
{
app('log')->debug('New release is also a beta!');
$message = (string)trans(
'firefly.update_new_version_alert',
[
'your_version' => $current,
'new_version' => $latest,
'date' => $date->isoFormat((string)trans('config.month_and_day_js')),
]
);
return [
'level' => 'success',
'message' => sprintf('%s %s', $message, trans('firefly.update_version_beta')),
];
}
private function releasedNewVersion(string $current, string $latest, Carbon $date): array
{
app('log')->debug('New release is old enough.');
$message = (string)trans(
'firefly.update_new_version_alert',
[
'your_version' => $current,
'new_version' => $latest,
'date' => $date->isoFormat((string)trans('config.month_and_day_js')),
]
);
app('log')->debug('New release is here!', [$message]);
event(new NewVersionAvailable($message));
return [
'level' => 'success',
'message' => $message,
];
}
}