From 4c4023bbc24645c7ef167a761dad27a5c5e68aa6 Mon Sep 17 00:00:00 2001 From: Pig Fang Date: Sat, 6 Apr 2019 22:52:43 +0800 Subject: [PATCH] Refactor `UpdateController` --- app/Http/Controllers/UpdateController.php | 145 ++++------------------ resources/lang/en/admin.yml | 7 +- resources/lang/zh_CN/admin.yml | 7 +- resources/views/admin/update.blade.php | 14 +-- tests/UpdateControllerTest.php | 58 +++------ 5 files changed, 59 insertions(+), 172 deletions(-) diff --git a/app/Http/Controllers/UpdateController.php b/app/Http/Controllers/UpdateController.php index 86e20e46..d09c78f1 100644 --- a/app/Http/Controllers/UpdateController.php +++ b/app/Http/Controllers/UpdateController.php @@ -3,11 +3,7 @@ namespace App\Http\Controllers; use Log; -use File; -use Cache; -use Storage; use Exception; -use ZipArchive; use Illuminate\Support\Arr; use Illuminate\Http\Request; use Composer\Semver\Comparator; @@ -15,127 +11,46 @@ use App\Services\PackageManager; class UpdateController extends Controller { - /** - * Current application version. - * - * @var string - */ protected $currentVersion; - - /** - * Latest application version in update source. - * - * @var string - */ - protected $latestVersion; - - /** - * Where to get information of new application versions. - * - * @var string - */ protected $updateSource; - - /** - * Updates information fetched from update source. - * - * @var array|null - */ - protected $updateInfo; - - /** - * Guzzle HTTP client. - * - * @var \GuzzleHttp\Client - */ protected $guzzle; + protected $error; + protected $info = []; public function __construct(\GuzzleHttp\Client $guzzle) { $this->updateSource = config('app.update_source'); $this->currentVersion = config('app.version'); - $this->guzzle = $guzzle; } public function showUpdatePage() { $info = [ - 'latest_version' => '', - 'current_version' => $this->currentVersion, - 'release_note' => '', - 'release_url' => '', - 'pre_release' => false, - // Fallback to current time - 'release_time' => '', - 'new_version_available' => false, + 'latest' => Arr::get($this->getUpdateInfo(), 'latest'), + 'current' => $this->currentVersion, ]; - - // If current update source is available - if ($this->getUpdateInfo()) { - $info['latest_version'] = $this->getUpdateInfo('latest_version'); - - $info['new_version_available'] = Comparator::greaterThan( - $info['latest_version'], - $info['current_version'] - ); - - if ($detail = $this->getReleaseInfo($info['latest_version'])) { - $info = array_merge($info, Arr::only($detail, [ - 'release_note', - 'release_url', - 'release_time', - 'pre_release', - ])); - } else { - // if detailed release info is not given - $info['new_version_available'] = false; - } - - if (! $info['new_version_available']) { - $info['release_time'] = Arr::get($this->getReleaseInfo($this->currentVersion), 'release_time'); - } - } - - $connectivity = true; - - try { - $this->guzzle->request('GET', $this->updateSource); - } catch (Exception $e) { - $connectivity = $e->getMessage(); - } - - $extra = ['canUpdate' => $info['new_version_available']]; - return view('admin.update', compact('info', 'connectivity', 'extra')); + $error = $this->error; + $extra = ['canUpdate' => $this->canUpdate()]; + return view('admin.update', compact('info', 'error', 'extra')); } public function checkUpdates() { - return json([ - 'latest' => $this->getUpdateInfo('latest_version'), - 'available' => $this->newVersionAvailable(), - ]); - } - - protected function newVersionAvailable() - { - $latest = $this->getUpdateInfo('latest_version'); - - return Comparator::greaterThan($latest, $this->currentVersion) && $this->getReleaseInfo($latest); + return json(['available' => $this->canUpdate()]); } public function download(Request $request, PackageManager $package) { - if (! $this->newVersionAvailable()) { + if (! $this->canUpdate()) { return json([]); } - $url = $this->getReleaseInfo($this->latestVersion)['release_url']; - $path = storage_path('packages/bs_'.$this->latestVersion.'.zip'); + $path = storage_path('packages/bs_'.$this->info['latest'].'.zip'); switch ($request->get('action')) { case 'download': try { - $package->download($url, $path)->extract(base_path()); + $package->download($this->info['url'], $path)->extract(base_path()); return json(trans('admin.update.complete'), 0); } catch (Exception $e) { report($e); @@ -148,36 +63,28 @@ class UpdateController extends Controller } } - protected function getUpdateInfo($key = null) + protected function getUpdateInfo() { - if (! $this->updateInfo) { - // Add timestamp to control cdn cache - $url = starts_with($this->updateSource, 'http') - ? $this->updateSource.'?v='.substr(time(), 0, -3) - : $this->updateSource; - + $acceptableSpec = 1; + if (! $this->info) { try { - $response = $this->guzzle->request('GET', $url)->getBody(); + $json = $this->guzzle->request('GET', $this->updateSource)->getBody(); + $info = json_decode($json, true); + if (Arr::get($info, 'spec') == $acceptableSpec) { + $this->info = $info; + } else { + $this->error = trans('admin.update.spec'); + } } catch (Exception $e) { - Log::error('[CheckingUpdate] Failed to get update information: '.$e->getMessage()); - } - - if (isset($response)) { - $this->updateInfo = json_decode($response, true); + $this->error = $e->getMessage(); } } - - $this->latestVersion = Arr::get($this->updateInfo, 'latest_version', $this->currentVersion); - - if (! is_null($key)) { - return Arr::get($this->updateInfo, $key); - } - - return $this->updateInfo; + return $this->info; } - protected function getReleaseInfo($version) + protected function canUpdate() { - return Arr::get($this->getUpdateInfo('releases'), $version); + $this->getUpdateInfo(); + return Comparator::greaterThan(Arr::get($this->info, 'latest'), $this->currentVersion); } } diff --git a/resources/lang/en/admin.yml b/resources/lang/en/admin.yml index 2b695c06..9679a77e 100644 --- a/resources/lang/en/admin.yml +++ b/resources/lang/en/admin.yml @@ -105,17 +105,16 @@ update: up-to-date: Already up-to-date. available: New version available. - pre-release-warning: This update is a pre-release, please double check before updating. versions: latest: "Latest Version:" current: "Current Version:" - pre-release: You are now using pre-release version. - check-github: Check GitHub Releases button: Update Now + spec: Current update source is not supported. + cautions: title: Cautions text: | @@ -128,7 +127,7 @@ update: size: "Size of package:" errors: - connection: "Unable to access to current update source. Details:" + connection: "Unable to access to current update source. Details: :error" download: errors: diff --git a/resources/lang/zh_CN/admin.yml b/resources/lang/zh_CN/admin.yml index 7002d175..484f1632 100644 --- a/resources/lang/zh_CN/admin.yml +++ b/resources/lang/zh_CN/admin.yml @@ -110,17 +110,16 @@ update: up-to-date: 已更新至最新版本。 available: 有更新可用。 - pre-release-warning: 本次更新为预发布版,请谨慎选择是否更新。 versions: latest: 最新版本: current: 当前版本: - pre-release: 当前版本为未发布测试版 - check-github: 查看 GitHub Releases button: 马上升级 + spec: 不支持当前的更新源。 + cautions: title: 注意事项 text: | @@ -133,7 +132,7 @@ update: size: 更新包大小: errors: - connection: 无法访问当前更新源。详细信息: + connection: 无法访问当前更新源。详细信息::error download: errors: diff --git a/resources/views/admin/update.blade.php b/resources/views/admin/update.blade.php index 391ff374..010bf38d 100644 --- a/resources/views/admin/update.blade.php +++ b/resources/views/admin/update.blade.php @@ -22,20 +22,20 @@

@lang('admin.update.info.title')

- @if ($info['new_version_available']) + @if ($extra['canUpdate'])
@lang('admin.update.info.available')
@@ -43,10 +43,10 @@
@lang('admin.update.info.versions.latest') - v{{ $info['latest_version'] }} + v{{ $info['latest'] }}
@lang('admin.update.info.versions.current') - v{{ $info['current_version'] }} + v{{ $info['current'] }}
@else - @if ($connectivity === true) -
{{ trans('admin.update.info.up-to-date') }}
+ @if (is_string($error)) +
{{ trans('admin.update.errors.connection', ['error' => $error]) }}
@else -
{{ trans('admin.update.errors.connection', ['error' => $connectivity]) }}
+
{{ trans('admin.update.info.up-to-date') }}
@endif @@ -54,7 +54,7 @@ diff --git a/tests/UpdateControllerTest.php b/tests/UpdateControllerTest.php index 50126a10..33755477 100644 --- a/tests/UpdateControllerTest.php +++ b/tests/UpdateControllerTest.php @@ -32,18 +32,20 @@ class UpdateControllerTest extends TestCase // Can't connect to update source $this->appendToGuzzleQueue([ new RequestException('Connection Error', new Request('GET', 'whatever')), - new RequestException('Connection Error', new Request('GET', 'whatever')), ]); $this->get('/admin/update')->assertSee(config('app.version')); - // New version available - $time = time(); - $this->appendToGuzzleQueue(200, [], $this->generateFakeUpdateInfo('8.9.3', false, $time)); - $this->get('/admin/update')->assertSee(config('app.version'))->assertSee('8.9.3'); + // Missing `spec` field + $this->appendToGuzzleQueue([ + new Response(200, [], json_encode(['latest' => '8.9.3', 'url' => ''])), + ]); + $this->get('/admin/update')->assertSee(trans('admin.update.spec')); - // Now using pre-release version - $this->appendToGuzzleQueue(200, [], $this->generateFakeUpdateInfo('0.0.1', false, $time)); - $this->get('/admin/update'); + // New version available + $this->appendToGuzzleQueue([ + new Response(200, [], $this->mockFakeUpdateInfo('8.9.3')), + ]); + $this->get('/admin/update')->assertSee(config('app.version'))->assertSee('8.9.3'); } public function testCheckUpdates() @@ -53,21 +55,12 @@ class UpdateControllerTest extends TestCase // Update source is unavailable $this->appendToGuzzleQueue([ new RequestException('Connection Error', new Request('GET', 'whatever')), - new RequestException('Connection Error', new Request('GET', 'whatever')), ]); - $this->getJson('/admin/update/check') - ->assertJson([ - 'latest' => null, - 'available' => false, - ]); + $this->getJson('/admin/update/check')->assertJson(['available' => false]); // New version available - $this->appendToGuzzleQueue(200, [], $this->generateFakeUpdateInfo('8.9.3', false, time())); - $this->getJson('/admin/update/check') - ->assertJson([ - 'latest' => '8.9.3', - 'available' => true, - ]); + $this->appendToGuzzleQueue(200, [], $this->mockFakeUpdateInfo('8.9.3')); + $this->getJson('/admin/update/check')->assertJson(['available' => true]); } public function testDownload() @@ -80,8 +73,8 @@ class UpdateControllerTest extends TestCase // Download $this->appendToGuzzleQueue([ - new Response(200, [], $this->generateFakeUpdateInfo('8.9.3')), - new Response(200, [], $this->generateFakeUpdateInfo('8.9.3')), + new Response(200, [], $this->mockFakeUpdateInfo('8.9.3')), + new Response(200, [], $this->mockFakeUpdateInfo('8.9.3')), ]); app()->instance(PackageManager::class, new Concerns\FakePackageManager(null, true)); $this->getJson('/admin/update/download?action=download') @@ -95,7 +88,7 @@ class UpdateControllerTest extends TestCase ->assertSee('0'); // Invalid action - $this->appendToGuzzleQueue(200, [], $this->generateFakeUpdateInfo('8.9.3')); + $this->appendToGuzzleQueue(200, [], $this->mockFakeUpdateInfo('8.9.3')); $this->getJson('/admin/update/download?action=no') ->assertJson([ 'errno' => 1, @@ -103,23 +96,12 @@ class UpdateControllerTest extends TestCase ]); } - protected function generateFakeUpdateInfo($version, $preview = false, $time = null) + protected function mockFakeUpdateInfo($version) { - $time = $time ?: time(); - return json_encode([ - 'app_name' => 'blessing-skin-server', - 'latest_version' => $version, - 'update_time' => $time, - 'releases' => [ - $version => [ - 'version' => $version, - 'pre_release' => $preview, - 'release_time' => $time, - 'release_note' => 'test', - 'release_url' => "https://whatever.test/$version/update.zip", - ], - ], + 'spec' => 1, + 'latest' => $version, + 'url' => "https://whatever.test/$version/update.zip", ]); } }
@lang('admin.update.info.versions.current') - v{{ $info['current_version'] }} + v{{ $info['current'] }}