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 ;
2024-02-14 06:34:38 +01:00
use Illuminate\Support\Facades\Log ;
2019-10-26 14:42:51 +02:00
/**
* 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
];
2024-02-14 06:34:38 +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:
2024-02-14 06:34:38 +01:00
$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
];
2024-02-14 06:34:38 +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 ;
}
2024-02-14 06:34:38 +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.
2024-02-14 06:34:38 +01:00
$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 ;
}
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-14 06:34:38 +01:00
$return = [
2020-02-02 10:39:37 +01:00
'level' => 'error' ,
2022-12-29 19:42:26 +01:00
'message' => ( string ) trans ( 'firefly.unknown_error' ),
2020-02-02 10:39:37 +01:00
];
2024-02-14 06:34:38 +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 );
}
2024-02-14 06:34:38 +01:00
if ( str_starts_with ( $current , 'develop' )) {
Log :: debug ( sprintf ( 'User is running develop version "%s"' , $current ));
$parts = explode ( '/' , $current );
$devDate = Carbon :: createFromFormat ( 'Y-m-d' , $parts [ 1 ]);
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 ;
}
2023-03-04 07:18:20 +01:00
2024-02-14 06:34:38 +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 ) {
$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 */
2024-02-14 06:34:38 +01:00
$released = $information [ 'date' ];
$today = today ( config ( 'app.timezone' )) -> startOfDay ();
$diff = $today -> diffInDays ( $released );
$expectedDiff = config ( 'firefly.update_minimum_age' ) ? ? 6 ;
2020-02-02 10:39:37 +01:00
// 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.
2024-02-14 06:34:38 +01:00
$isBeta = $information [ 'is_beta' ] ? ? false ;
2020-02-02 10:39:37 +01:00
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
}
2024-02-14 06:34:38 +01:00
$isAlpha = $information [ 'is_alpha' ] ? ? false ;
2020-02-02 10:39:37 +01:00
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
}