From 98e8a8072f49608c7eff85bd842cb48ee7b842dc Mon Sep 17 00:00:00 2001 From: cuneytsenturk Date: Thu, 27 Sep 2018 17:08:00 +0300 Subject: [PATCH] Improve the update process --- app/Http/Controllers/Install/Updates.php | 246 +++++++++++++++++- app/Utilities/Updater.php | 52 +++- resources/lang/en-GB/modules.php | 12 + .../views/install/updates/edit.blade.php | 117 +++++++++ routes/web.php | 7 + 5 files changed, 427 insertions(+), 7 deletions(-) create mode 100644 resources/views/install/updates/edit.blade.php diff --git a/app/Http/Controllers/Install/Updates.php b/app/Http/Controllers/Install/Updates.php index 855050e75..0b277bab2 100644 --- a/app/Http/Controllers/Install/Updates.php +++ b/app/Http/Controllers/Install/Updates.php @@ -6,8 +6,10 @@ use App\Http\Controllers\Controller; use App\Events\UpdateFinished; use App\Utilities\Updater; use App\Utilities\Versions; +use Illuminate\Http\Request; use Artisan; use Module; +use File; class Updates extends Controller { @@ -80,15 +82,20 @@ class Updates extends Controller */ public function update($alias, $version) { - set_time_limit(600); // 10 minutes + if ($alias == 'core') { + $name = 'Akaunting v' . $version; - if (Updater::update($alias, $version)) { - return redirect('install/updates/post/' . $alias . '/' . version('short') . '/' . $version); + $installed = version('short'); + } else { + // Get module instance + $module = Module::findByAlias($alias); + + $name = $module->get('name'); + + $installed = $module->get('version'); } - flash(trans('updates.error'))->error()->important(); - - return redirect()->back(); + return view('install.updates.edit', compact('alias', 'name', 'installed', 'version')); } /** @@ -117,4 +124,231 @@ class Updates extends Controller return redirect('install/updates'); } + + /** + * Show the form for viewing the specified resource. + * + * @param $request + * + * @return Response + */ + public function steps(Request $request) + { + $this->checkApiToken(); + + $json = []; + $json['step'] = []; + + $name = $request['name']; + $version = $request['version']; + + // Download + $json['step'][] = [ + 'text' => trans('modules.installation.download', ['module' => $name]), + 'url' => url('install/updates/download') + ]; + + // Unzip + $json['step'][] = [ + 'text' => trans('modules.installation.unzip', ['module' => $name]), + 'url' => url('install/updates/unzip') + ]; + + // File Copy + $json['step'][] = [ + 'text' => trans('modules.installation.file_copy', ['module' => $name]), + 'url' => url('install/updates/file-copy') + ]; + + // Migrate DB and trigger event UpdateFinish event + $json['step'][] = [ + 'text' => trans('modules.installation.migrate', ['module' => $name]), + 'url' => url('install/updates/migrate') + ]; + + // redirect update page + $json['step'][] = [ + 'text' => trans('modules.installation.finish'), + 'url' => url('install/updates/finish') + ]; + + return response()->json($json); + } + + /** + * Show the form for viewing the specified resource. + * + * @param $request + * + * @return Response + */ + public function download(Request $request) + { + set_time_limit(600); // 10 minutes + + $status = true; + + if ($request['alias'] != 'core') { + $this->checkApiToken(); + } + + // Download file + if (!$data = Updater::download($request['alias'], $request['version'])) { + $status = false; + + $message = trans('modules.errors.download', ['module' => $request['name']]); + } + + // Create temp directory + $path = 'temp-' . md5(mt_rand()); + $temp_path = storage_path('app/temp') . '/' . $path; + + if (!File::isDirectory($temp_path)) { + File::makeDirectory($temp_path); + } + + $file = $temp_path . '/upload.zip'; + + // Add content to the Zip file + $uploaded = is_int(file_put_contents($file, $data)) ? true : false; + + if (!$uploaded) { + return false; + + $message = trans('modules.errors.upload', ['module' => $request['name']]); + } + + $json = [ + 'success' => ($status) ? true : false, + 'errors' => (!$status) ? $message : false, + 'data' => [ + 'path' => $path + ] + ]; + + return response()->json($json); + } + + /** + * Show the form for viewing the specified resource. + * + * @param $request + * + * @return Response + */ + public function unzip(Request $request) + { + set_time_limit(600); // 10 minutes + + if ($request['alias'] != 'core') { + $this->checkApiToken(); + } + + $path = storage_path('app/temp') . '/' . $request['path']; + + $file = $path . '/upload.zip'; + + $result = Updater::unzip($file, $path); + + $json = [ + 'success' => ($result) ? true : false, + 'errors' => (!$result) ? trans('modules.errors.unzip', ['module' => $request['name']]) : false, + 'data' => [ + 'path' => $request['path'] + ] + ]; + + return response()->json($json); + } + + /** + * Show the form for viewing the specified resource. + * + * @param $request + * + * @return Response + */ + public function fileCopy(Request $request) + { + set_time_limit(600); // 10 minutes + + if ($request['alias'] != 'core') { + $this->checkApiToken(); + } + + $path = storage_path('app/temp') . '/' . $request['path']; + + $result = Updater::fileCopy($request['alias'], $path, $request['version']); + + $json = [ + 'success' => ($result) ? true : false, + 'errors' => (!$result) ? trans('modules.errors.file_copy', ['module' => $request['name']]) : false, + 'data' => [ + 'path' => $request['path'] + ] + ]; + + return response()->json($json); + } + + /** + * Show the form for viewing the specified resource. + * + * @param $request + * + * @return Response + */ + public function migrate(Request $request) + { + // Check if the file mirror was successful + if (($request['alias'] == 'core') && (version('short') != $request['version'])) { + $json = [ + 'success' => false, + 'errors' => trans('modules.errors.migrate core', ['module' => $request['name']]), + 'data' => [] + ]; + + return response()->json($json); + } + + // Clear cache after update + Artisan::call('cache:clear'); + + try { + event(new UpdateFinished($request['alias'], $request['installed'], $request['version'])); + + $json = [ + 'success' => true, + 'errors' => false, + 'data' => [] + ]; + } catch (\Exception $e) { + $json = [ + 'success' => false, + 'errors' => trans('modules.errors.migrate', ['module' => $request['name']]), + 'data' => [] + ]; + } + + return response()->json($json); + } + + /** + * Show the form for viewing the specified resource. + * + * @param $request + * + * @return Response + */ + public function finish(Request $request) + { + $json = [ + 'success' => true, + 'errors' => false, + 'redirect' => url("install/updates"), + 'data' => [], + ]; + + return response()->json($json); + } } diff --git a/app/Utilities/Updater.php b/app/Utilities/Updater.php index 6890f1038..2deddb51b 100644 --- a/app/Utilities/Updater.php +++ b/app/Utilities/Updater.php @@ -121,6 +121,56 @@ class Updater return $file; } + public static function unzip($file, $temp_path) + { + // Unzip the file + $zip = new ZipArchive(); + + if (($zip->open($file) !== true) || !$zip->extractTo($temp_path)) { + return false; + } + + $zip->close(); + + // Delete zip file + File::delete($file); + + return true; + } + + public static function fileCopy($alias, $temp_path, $version) + { + if ($alias == 'core') { + // Move all files/folders from temp path + if (!File::copyDirectory($temp_path, base_path())) { + return false; + } + } else { + // Get module instance + $module = Module::findByAlias($alias); + $model = Model::where('alias', $alias)->first(); + + // Move all files/folders from temp path + if (!File::copyDirectory($temp_path, module_path($module->get('name')))) { + return false; + } + + // Add history + ModelHistory::create([ + 'company_id' => session('company_id'), + 'module_id' => $model->id, + 'category' => $module->get('category'), + 'version' => $version, + 'description' => trans('modules.history.updated', ['module' => $module->get('name')]), + ]); + } + + // Delete temp directory + File::deleteDirectory($temp_path); + + return true; + } + public static function all() { // Get data from cache @@ -159,4 +209,4 @@ class Updater return $data; } -} \ No newline at end of file +} diff --git a/resources/lang/en-GB/modules.php b/resources/lang/en-GB/modules.php index ce62fd3cc..80a0bbd44 100644 --- a/resources/lang/en-GB/modules.php +++ b/resources/lang/en-GB/modules.php @@ -39,9 +39,21 @@ return [ 'header' => 'App Installation', 'download' => 'Downloading :module file.', 'unzip' => 'Extracting :module files.', + 'file_copy' => 'Copying :module files.', + 'migrate' => 'Applying :module updates.', + 'finish' => 'The update was successfully installed. You will be redirect Update Center.', 'install' => 'Installing :module files.', ], + 'errors' => [ + 'download' => ':module can not download!', + 'upload' => 'Downloaded :module can not saved!', + 'unzip' => ':module can not unzip!', + 'file_copy' => ':module files can not copy!', + 'migrate' => ':module migrate broken!', + 'migrate core' => ':module already latest version so then yon can not update.', + ], + 'badge' => [ 'installed' => 'Installed', ], diff --git a/resources/views/install/updates/edit.blade.php b/resources/views/install/updates/edit.blade.php new file mode 100644 index 000000000..eb671cbea --- /dev/null +++ b/resources/views/install/updates/edit.blade.php @@ -0,0 +1,117 @@ +@extends('layouts.admin') + +@section('title', trans_choice('general.updates', 2)) + +@section('new_button') +  {{ trans('updates.check') }} +@endsection + +@section('content') + +
+
+ +

{{ $name }}

+
+ + +
+

+

+
+ {{ trans('modules.installation.start', ['module' => $name]) }} +
+
+
+

+
+ +
+ +@endsection + +@push('scripts') + +@endpush diff --git a/routes/web.php b/routes/web.php index 6b47b051d..942e8df00 100644 --- a/routes/web.php +++ b/routes/web.php @@ -161,6 +161,13 @@ Route::group(['middleware' => 'language'], function () { Route::get('updates/check', 'Install\Updates@check'); Route::get('updates/update/{alias}/{version}', 'Install\Updates@update'); Route::get('updates/post/{alias}/{old}/{new}', 'Install\Updates@post'); + Route::post('updates/steps', 'Install\Updates@steps'); + Route::post('updates/download', 'Install\Updates@download'); + Route::post('updates/download', 'Install\Updates@download'); + Route::post('updates/unzip', 'Install\Updates@unzip'); + Route::post('updates/file-copy', 'Install\Updates@fileCopy'); + Route::post('updates/migrate', 'Install\Updates@migrate'); + Route::post('updates/finish', 'Install\Updates@finish'); Route::resource('updates', 'Install\Updates'); });