added module:download command

This commit is contained in:
Denis Duliçi 2020-12-24 02:16:00 +03:00
parent 5b0a50c758
commit 531dcd8dab
16 changed files with 793 additions and 515 deletions

View File

@ -0,0 +1,131 @@
<?php
namespace App\Console\Commands;
use App\Jobs\Install\CopyFiles;
use App\Jobs\Install\DownloadFile;
use App\Jobs\Install\UnzipFile;
use App\Traits\Jobs;
use App\Utilities\Versions;
use Illuminate\Console\Command;
class DownloadModule extends Command
{
use Jobs;
const CMD_SUCCESS = 0;
const CMD_ERROR = 1;
public $alias;
public $company;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'module:download {alias} {company}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Download the specified module.';
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
set_time_limit(3600); // 1 hour
$this->alias = $this->argument('alias');
$this->company = $this->argument('company');
session(['company_id' => $this->company]);
setting()->setExtraColumns(['company_id' => $this->company]);
if (!$path = $this->download()) {
return self::CMD_ERROR;
}
if (!$this->unzip($path)) {
return self::CMD_ERROR;
}
if (!$this->copyFiles($path)) {
return self::CMD_ERROR;
}
$this->info("Module [{$this->alias}] downloaded!");
return self::CMD_SUCCESS;
}
public function download()
{
$this->info('Downloading module...');
try {
$path = $this->dispatch(new DownloadFile($this->alias, $this->getVersion()));
} catch (\Exception $e) {
$this->error($e->getMessage());
return false;
}
return $path;
}
public function unzip($path)
{
$this->info('Unzipping module...');
try {
$this->dispatch(new UnzipFile($this->alias, $path));
} catch (\Exception $e) {
$this->error($e->getMessage());
return false;
}
return true;
}
public function copyFiles($path)
{
$this->info('Copying module files...');
try {
$this->dispatch(new CopyFiles($this->alias, $path));
event(new \App\Events\Module\Copied($this->alias, $this->company));
} catch (\Exception $e) {
$this->error($e->getMessage());
return false;
}
return true;
}
protected function getVersion()
{
$version = Versions::latest($this->alias);
if (empty($version)) {
$current = '1.0.0';
$url = 'apps/' . $this->alias . '/version/' . $current . '/' . version('short');
$version = Versions::getLatestVersion($url, $current);
}
return $version;
}
}

View File

@ -2,12 +2,21 @@
namespace App\Console\Commands;
use App\Utilities\Updater;
use App\Events\Install\UpdateCopied;
use App\Events\Install\UpdateDownloaded;
use App\Events\Install\UpdateUnzipped;
use App\Jobs\Install\CopyFiles;
use App\Jobs\Install\DownloadFile;
use App\Jobs\Install\FinishUpdate;
use App\Jobs\Install\UnzipFile;
use App\Traits\Jobs;
use App\Utilities\Versions;
use Illuminate\Console\Command;
class Update extends Command
{
use Jobs;
const CMD_SUCCESS = 0;
const CMD_ERROR = 1;
@ -96,7 +105,9 @@ class Update extends Command
$this->info('Downloading update...');
try {
$path = Updater::download($this->alias, $this->new, $this->old);
$path = $this->dispatch(new DownloadFile($this->alias, $this->new));
event(new UpdateDownloaded($this->alias, $this->new, $this->old));
} catch (\Exception $e) {
$this->error($e->getMessage());
@ -111,7 +122,9 @@ class Update extends Command
$this->info('Unzipping update...');
try {
Updater::unzip($path, $this->alias, $this->new, $this->old);
$this->dispatch(new UnzipFile($this->alias, $path));
event(new UpdateUnzipped($this->alias, $this->new, $this->old));
} catch (\Exception $e) {
$this->error($e->getMessage());
@ -126,7 +139,9 @@ class Update extends Command
$this->info('Copying update files...');
try {
Updater::copyFiles($path, $this->alias, $this->new, $this->old);
$this->dispatch(new CopyFiles($this->alias, $path));
event(new UpdateCopied($this->alias, $this->new, $this->old));
} catch (\Exception $e) {
$this->error($e->getMessage());
@ -141,7 +156,7 @@ class Update extends Command
$this->info('Finishing update...');
try {
Updater::finish($this->alias, $this->new, $this->old);
$this->dispatch(new FinishUpdate($this->alias, $this->new, $this->old));
} catch (\Exception $e) {
$this->error($e->getMessage());

View File

@ -3,8 +3,16 @@
namespace App\Http\Controllers\Install;
use App\Abstracts\Http\Controller;
use App\Utilities\Updater;
use App\Events\Install\UpdateCacheCleared;
use App\Events\Install\UpdateCopied;
use App\Events\Install\UpdateDownloaded;
use App\Events\Install\UpdateUnzipped;
use App\Jobs\Install\CopyFiles;
use App\Jobs\Install\DownloadFile;
use App\Jobs\Install\FinishUpdate;
use App\Jobs\Install\UnzipFile;
use App\Utilities\Versions;
use Illuminate\Support\Facades\Cache;
use Illuminate\Http\Request;
class Updates extends Controller
@ -16,7 +24,7 @@ class Updates extends Controller
*/
public function index()
{
$updates = Updater::all();
$updates = Versions::getUpdates();
$core = null;
@ -62,7 +70,10 @@ class Updates extends Controller
public function check()
{
// Clear cache in order to check for updates
Updater::clear();
Cache::forget('updates');
Cache::forget('versions');
event(new UpdateCacheCleared(session('company_id')));
return redirect()->back();
}
@ -155,7 +166,9 @@ class Updates extends Controller
set_time_limit(900); // 15 minutes
try {
$path = Updater::download($request['alias'], $request['version'], $request['installed']);
$path = $this->dispatch(new DownloadFile($request['alias'], $request['version']));
event(new UpdateDownloaded($request['alias'], $request['version'], $request['installed']));
$json = [
'success' => true,
@ -189,7 +202,9 @@ class Updates extends Controller
set_time_limit(900); // 15 minutes
try {
$path = Updater::unzip($request['path'], $request['alias'], $request['version'], $request['installed']);
$path = $this->dispatch(new UnzipFile($request['alias'], $request['path']));
event(new UpdateUnzipped($request['alias'], $request['version'], $request['installed']));
$json = [
'success' => true,
@ -223,7 +238,9 @@ class Updates extends Controller
set_time_limit(900); // 15 minutes
try {
$path = Updater::copyFiles($request['path'], $request['alias'], $request['version'], $request['installed']);
$path = $this->dispatch(new CopyFiles($request['alias'], $request['path']));
event(new UpdateCopied($request['alias'], $request['version'], $request['installed']));
$json = [
'success' => true,
@ -257,7 +274,7 @@ class Updates extends Controller
set_time_limit(900); // 15 minutes
try {
Updater::finish($request['alias'], $request['version'], $request['installed']);
$this->dispatch(new FinishUpdate($request['alias'], $request['version'], $request['installed']));
$json = [
'success' => true,

View File

@ -3,11 +3,16 @@
namespace App\Http\Controllers\Modules;
use App\Abstracts\Http\Controller;
use App\Jobs\Install\CopyFiles;
use App\Jobs\Install\DisableModule;
use App\Jobs\Install\DownloadFile;
use App\Jobs\Install\EnableModule;
use App\Jobs\Install\InstallModule;
use App\Jobs\Install\UninstallModule;
use App\Jobs\Install\UnzipFile;
use App\Models\Module\Module;
use App\Traits\Modules;
use File;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
class Item extends Controller
{
@ -83,9 +88,13 @@ class Item extends Controller
$name = $request['name'];
$alias = $request['alias'];
$module_path = config('module.paths.modules') . '/' . Str::studly($alias);
if (!File::isDirectory($module_path)) {
if ($this->moduleExists($alias)) {
// Install
$steps[] = [
'text' => trans('modules.installation.install', ['module' => $name]),
'url' => route('apps.install')
];
} else {
// Download
$steps[] = [
'text' => trans('modules.installation.download', ['module' => $name]),
@ -104,12 +113,6 @@ class Item extends Controller
'url' => route('apps.copy')
];
// Install
$steps[] = [
'text' => trans('modules.installation.install', ['module' => $name]),
'url' => route('apps.install')
];
} else {
// Install
$steps[] = [
'text' => trans('modules.installation.install', ['module' => $name]),
@ -134,13 +137,25 @@ class Item extends Controller
*/
public function download(Request $request)
{
$path = $request['path'];
try {
$path = $this->dispatch(new DownloadFile($request['alias'], $request['version']));
$version = $request['version'];
$path .= '/' . $version . '/' . version('short') . '/' . setting('apps.api_key');
$json = $this->downloadModule($path);
$json = [
'success' => true,
'error' => false,
'message' => null,
'data' => [
'path' => $path,
],
];
} catch (\Exception $e) {
$json = [
'success' => false,
'error' => true,
'message' => $e->getMessage(),
'data' => [],
];
}
return response()->json($json);
}
@ -154,9 +169,25 @@ class Item extends Controller
*/
public function unzip(Request $request)
{
$path = $request['path'];
try {
$path = $this->dispatch(new UnzipFile($request['alias'], $request['path']));
$json = $this->unzipModule($path);
$json = [
'success' => true,
'error' => false,
'message' => null,
'data' => [
'path' => $path,
],
];
} catch (\Exception $e) {
$json = [
'success' => false,
'error' => true,
'message' => $e->getMessage(),
'data' => [],
];
}
return response()->json($json);
}
@ -170,9 +201,27 @@ class Item extends Controller
*/
public function copy(Request $request)
{
$path = $request['path'];
try {
$this->dispatch(new CopyFiles($request['alias'], $request['path']));
$json = $this->copyModule($path);
event(new \App\Events\Module\Copied($request['alias'], session('company_id')));
$json = [
'success' => true,
'error' => false,
'message' => null,
'data' => [
'alias' => $request['alias'],
],
];
} catch (\Exception $e) {
$json = [
'success' => false,
'error' => true,
'message' => $e->getMessage(),
'data' => [],
];
}
return response()->json($json);
}
@ -186,16 +235,36 @@ class Item extends Controller
*/
public function install(Request $request)
{
$alias = $request['alias'];
try {
$this->dispatch(new InstallModule($request['alias']));
$json = $this->installModule($alias);
$name = module($request['alias'])->getName();
if ($json['success']) {
$message = trans('modules.installed', ['module' => $json['data']['name']]);
$message = trans('modules.installed', ['module' => $name]);
flash($message)->success();
} else {
flash($json['message'])->error();
$json = [
'success' => true,
'error' => false,
'message' => null,
'redirect' => route('apps.app.show', $request['alias']),
'data' => [
'name' => $name,
'alias' => $request['alias'],
],
];
} catch (\Exception $e) {
$message = $e->getMessage();
flash($message)->error();
$json = [
'success' => false,
'error' => true,
'message' => $message,
'data' => [],
];
}
return response()->json($json);
@ -203,14 +272,18 @@ class Item extends Controller
public function uninstall($alias)
{
$json = $this->uninstallModule($alias);
try {
$name = module($alias)->getName();
if ($json['success']) {
$message = trans('modules.uninstalled', ['module' => $json['data']['name']]);
$this->dispatch(new UninstallModule($alias));
$message = trans('modules.uninstalled', ['module' => $name]);
flash($message)->success();
} else {
flash($json['message'])->error();
} catch (\Exception $e) {
$message = $e->getMessage();
flash($message)->error();
}
return redirect()->route('apps.app.show', $alias)->send();
@ -218,14 +291,18 @@ class Item extends Controller
public function enable($alias)
{
$json = $this->enableModule($alias);
try {
$name = module($alias)->getName();
if ($json['success']) {
$message = trans('modules.enabled', ['module' => $json['data']['name']]);
$this->dispatch(new EnableModule($alias));
$message = trans('modules.enabled', ['module' => $name]);
flash($message)->success();
} else {
flash($json['message'])->error();
} catch (\Exception $e) {
$message = $e->getMessage();
flash($message)->error();
}
return redirect()->route('apps.app.show', $alias)->send();
@ -233,14 +310,18 @@ class Item extends Controller
public function disable($alias)
{
$json = $this->disableModule($alias);
try {
$name = module($alias)->getName();
if ($json['success']) {
$message = trans('modules.disabled', ['module' => $json['data']['name']]);
$this->dispatch(new DisableModule($alias));
$message = trans('modules.disabled', ['module' => $name]);
flash($message)->success();
} else {
flash($json['message'])->error();
} catch (\Exception $e) {
$message = $e->getMessage();
flash($message)->error();
}
return redirect()->route('apps.app.show', $alias)->send();

View File

@ -2,13 +2,13 @@
namespace App\Http\ViewComposers;
use App\Utilities\Updater;
use App\Utilities\Versions;
use App\Traits\Modules;
use Illuminate\View\View;
use App\Traits\Modules as RemoteModules;
class Header
{
use RemoteModules;
use Modules;
/**
* Bind data to the view.
@ -35,12 +35,12 @@ class Header
];
}
$undereads = $user->unreadNotifications;
$unreads = $user->unreadNotifications;
foreach ($undereads as $underead) {
$data = $underead->getAttribute('data');
foreach ($unreads as $unread) {
$data = $unread->getAttribute('data');
switch ($underead->getAttribute('type')) {
switch ($unread->getAttribute('type')) {
case 'App\Notifications\Purchase\Bill':
$bills[$data['bill_id']] = $data['amount'];
$notifications++;
@ -52,7 +52,7 @@ class Header
}
}
$updates = count(Updater::all());
$updates = count(Versions::getUpdates());
$this->loadSuggestions();
}

View File

@ -0,0 +1,77 @@
<?php
namespace App\Jobs\Install;
use App\Abstracts\Job;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
class CopyFiles extends Job
{
protected $alias;
protected $path;
/**
* Create a new job instance.
*
* @param $alias
* @param $path
*/
public function __construct($alias, $path)
{
$this->alias = $alias;
$this->path = $path;
}
/**
* Execute the job.
*
* @return string
*/
public function handle()
{
if (empty($this->path)) {
throw new \Exception(trans('modules.errors.file_copy', ['module' => $this->alias]));
}
$source = storage_path('app/temp/' . $this->path);
$destination = $this->getDestination($source);
// Move all files/folders from temp path
if (!File::copyDirectory($source, $destination)) {
throw new \Exception(trans('modules.errors.file_copy', ['module' => $this->alias]));
}
// Delete temp directory
File::deleteDirectory($source);
}
protected function getDestination($source)
{
if ($this->alias == 'core') {
return base_path();
}
if (!is_file($source . '/module.json')) {
throw new \Exception(trans('modules.errors.file_copy', ['module' => $this->alias]));
}
$modules_path = config('module.paths.modules');
// Create modules directory
if (!File::isDirectory($modules_path)) {
File::makeDirectory($modules_path);
}
$module_path = $modules_path . '/' . Str::studly($this->alias);
// Create module directory
if (!File::isDirectory($module_path)) {
File::makeDirectory($module_path);
}
return $module_path;
}
}

View File

@ -0,0 +1,45 @@
<?php
namespace App\Jobs\Install;
use App\Abstracts\Job;
use App\Utilities\Console;
class DisableModule extends Job
{
protected $alias;
protected $company_id;
protected $locale;
/**
* Create a new job instance.
*
* @param $alias
* @param $company_id
* @param $locale
*/
public function __construct($alias, $company_id = null, $locale = null)
{
$this->alias = $alias;
$this->company_id = $company_id ?: session('company_id');
$this->locale = $locale ?: app()->getLocale();
}
/**
* Execute the job.
*
* @return string
*/
public function handle()
{
$command = "module:disable {$this->alias} {$this->company_id} {$this->locale}";
$result = Console::run($command);
if ($result !== true) {
throw new \Exception($result);
}
}
}

View File

@ -0,0 +1,75 @@
<?php
namespace App\Jobs\Install;
use App\Abstracts\Job;
use App\Traits\SiteApi;
use App\Utilities\Info;
use Illuminate\Support\Facades\File;
class DownloadFile extends Job
{
use SiteApi;
protected $alias;
protected $version;
/**
* Create a new job instance.
*
* @param $alias
* @param $version
*/
public function __construct($alias, $version)
{
$this->alias = $alias;
$this->version = $version;
}
/**
* Execute the job.
*
* @return string
*/
public function handle()
{
if (!$response = static::getResponse('GET', $this->getUrl(), ['timeout' => 50, 'track_redirects' => true])) {
throw new \Exception(trans('modules.errors.download', ['module' => $this->alias]));
}
$file = $response->getBody()->getContents();
$path = 'temp-' . md5(mt_rand());
$temp_path = storage_path('app/temp/' . $path);
$file_path = $temp_path . '/upload.zip';
// Create tmp directory
if (!File::isDirectory($temp_path)) {
File::makeDirectory($temp_path);
}
// Add content to the Zip file
$uploaded = is_int(file_put_contents($file_path, $file)) ? true : false;
if (!$uploaded) {
throw new \Exception(trans('modules.errors.download', ['module' => $this->alias]));
}
return $path;
}
protected function getUrl()
{
if ($this->alias == 'core') {
$info = Info::all();
$url = 'core/download/' . $this->version . '/' . $info['php'] . '/' . $info['mysql'];
} else {
$url = 'apps/' . $this->alias . '/download/' . $this->version . '/' . version('short') . '/' . setting('apps.api_key');
}
return $url;
}
}

View File

@ -0,0 +1,45 @@
<?php
namespace App\Jobs\Install;
use App\Abstracts\Job;
use App\Utilities\Console;
class EnableModule extends Job
{
protected $alias;
protected $company_id;
protected $locale;
/**
* Create a new job instance.
*
* @param $alias
* @param $company_id
* @param $locale
*/
public function __construct($alias, $company_id = null, $locale = null)
{
$this->alias = $alias;
$this->company_id = $company_id ?: session('company_id');
$this->locale = $locale ?: app()->getLocale();
}
/**
* Execute the job.
*
* @return string
*/
public function handle()
{
$command = "module:enable {$this->alias} {$this->company_id} {$this->locale}";
$result = Console::run($command);
if ($result !== true) {
throw new \Exception($result);
}
}
}

View File

@ -0,0 +1,56 @@
<?php
namespace App\Jobs\Install;
use App\Abstracts\Job;
use App\Models\Module\Module;
use App\Utilities\Console;
class FinishUpdate extends Job
{
protected $alias;
protected $new;
protected $old;
/**
* Create a new job instance.
*
* @param $alias
* @param $new
* @param $old
*/
public function __construct($alias, $new, $old)
{
$this->alias = $alias;
$this->new = $new;
$this->old = $old;
}
/**
* Execute the job.
*
* @return string
*/
public function handle()
{
if ($this->alias == 'core') {
$companies = [session('company_id')];
} else {
$companies = Module::alias($this->alias)->allCompanies()->cursor();
}
foreach ($companies as $company) {
$company_id = is_object($company) ? $company->id : $company;
$command = "update:finish {$this->alias} {$company_id} {$this->new} {$this->old}";
if (true !== $result = Console::run($command)) {
$message = !empty($result) ? $result : trans('modules.errors.finish', ['module' => $this->alias]);
throw new \Exception($message);
}
}
}
}

View File

@ -0,0 +1,47 @@
<?php
namespace App\Jobs\Install;
use App\Abstracts\Job;
use App\Utilities\Console;
class InstallModule extends Job
{
protected $alias;
protected $company_id;
protected $locale;
/**
* Create a new job instance.
*
* @param $alias
* @param $company_id
* @param $locale
*/
public function __construct($alias, $company_id = null, $locale = null)
{
$this->alias = $alias;
$this->company_id = $company_id ?: session('company_id');
$this->locale = $locale ?: app()->getLocale();
}
/**
* Execute the job.
*
* @return string
*/
public function handle()
{
$command = "module:install {$this->alias} {$this->company_id} {$this->locale}";
$result = Console::run($command);
if ($result !== true) {
$message = !empty($result) ? $result : trans('modules.errors.finish', ['module' => $this->alias]);
throw new \Exception($message);
}
}
}

View File

@ -0,0 +1,45 @@
<?php
namespace App\Jobs\Install;
use App\Abstracts\Job;
use App\Utilities\Console;
class UninstallModule extends Job
{
protected $alias;
protected $company_id;
protected $locale;
/**
* Create a new job instance.
*
* @param $alias
* @param $company_id
* @param $locale
*/
public function __construct($alias, $company_id = null, $locale = null)
{
$this->alias = $alias;
$this->company_id = $company_id ?: session('company_id');
$this->locale = $locale ?: app()->getLocale();
}
/**
* Execute the job.
*
* @return string
*/
public function handle()
{
$command = "module:uninstall {$this->alias} {$this->company_id} {$this->locale}";
$result = Console::run($command);
if ($result !== true) {
throw new \Exception($result);
}
}
}

View File

@ -0,0 +1,56 @@
<?php
namespace App\Jobs\Install;
use App\Abstracts\Job;
use Illuminate\Support\Facades\File;
use ZipArchive;
class UnzipFile extends Job
{
protected $alias;
protected $path;
/**
* Create a new job instance.
*
* @param $alias
* @param $path
*/
public function __construct($alias, $path)
{
$this->alias = $alias;
$this->path = $path;
}
/**
* Execute the job.
*
* @return string
*/
public function handle()
{
if (empty($this->path)) {
throw new \Exception(trans('modules.errors.unzip', ['module' => $this->alias]));
}
$temp_path = storage_path('app/temp/' . $this->path);
$file = $temp_path . '/upload.zip';
// Unzip the file
$zip = new ZipArchive();
if (!$zip->open($file) || !$zip->extractTo($temp_path)) {
throw new \Exception(trans('modules.errors.unzip', ['module' => $this->alias]));
}
$zip->close();
// Remove Zip
File::delete($file);
return $this->path;
}
}

View File

@ -294,268 +294,6 @@ trait Modules
return $response->json();
}
public function downloadModule($path)
{
if (empty($path)) {
return [
'success' => false,
'error' => true,
'message' => trans('modules.errors.download', ['module' => '']),
'data' => null,
];
}
if (!$response = static::getResponse('GET', $path)) {
return [
'success' => false,
'error' => true,
'message' => trans('modules.errors.download', ['module' => '']),
'data' => null,
];
}
$file = $response->getBody()->getContents();
$path = 'temp-' . md5(mt_rand());
$temp_path = storage_path('app/temp/' . $path);
$file_path = $temp_path . '/upload.zip';
// Create tmp directory
if (!File::isDirectory($temp_path)) {
File::makeDirectory($temp_path);
}
// Add content to the Zip file
$uploaded = is_int(file_put_contents($file_path, $file)) ? true : false;
if (!$uploaded) {
return [
'success' => false,
'error' => true,
'message' => trans('modules.errors.download', ['module' => '']),
'data' => null,
];
}
return [
'success' => true,
'error' => false,
'message' => null,
'data' => [
'path' => $path,
],
];
}
public function unzipModule($path)
{
if (empty($path)) {
return [
'success' => false,
'error' => true,
'message' => trans('modules.errors.unzip', ['module' => '']),
'data' => null,
];
}
$temp_path = storage_path('app/temp/' . $path);
$file = $temp_path . '/upload.zip';
// Unzip the file
$zip = new ZipArchive();
if (!$zip->open($file) || !$zip->extractTo($temp_path)) {
return [
'success' => false,
'error' => true,
'message' => trans('modules.errors.unzip', ['module' => '']),
'data' => null,
];
}
$zip->close();
// Remove Zip
File::delete($file);
return [
'success' => true,
'error' => false,
'message' => null,
'data' => [
'path' => $path,
],
];
}
public function copyModule($path)
{
$temp_path = storage_path('app/temp/' . $path);
if (empty($path) || !is_file($temp_path . '/module.json')) {
return [
'success' => false,
'error' => true,
'message' => trans('modules.errors.finish', ['module' => '']),
'data' => null,
];
}
$modules_path = config('module.paths.modules');
// Create modules directory
if (!File::isDirectory($modules_path)) {
File::makeDirectory($modules_path);
}
$module = json_decode(file_get_contents($temp_path . '/module.json'));
$module_path = $modules_path . '/' . Str::studly($module->alias);
// Create module directory
if (!File::isDirectory($module_path)) {
File::makeDirectory($module_path);
}
// Move all files/folders from temp path then delete it
File::copyDirectory($temp_path, $module_path);
File::deleteDirectory($temp_path);
event(new \App\Events\Module\Copied($module->alias, session('company_id')));
return [
'success' => true,
'error' => false,
'message' => null,
'data' => [
'path' => $path,
'alias' => $module->alias,
],
];
}
public function installModule($alias)
{
$company_id = session('company_id');
$locale = app()->getLocale();
$command = "module:install {$alias} {$company_id} {$locale}";
if (true !== $result = Console::run($command)) {
$message = !empty($result) ? $result : trans('modules.errors.finish', ['module' => $alias]);
return [
'success' => false,
'error' => true,
'message' => $message,
'data' => null,
];
}
return [
'success' => true,
'redirect' => route('apps.app.show', $alias),
'error' => false,
'message' => null,
'data' => [
'path' => '',
'name' => module($alias)->getName(),
'alias' => $alias,
],
];
}
public function uninstallModule($alias)
{
$module = module($alias);
$name = $module->getName();
$version = $module->get('version');
$company_id = session('company_id');
$locale = app()->getLocale();
$command = "module:uninstall {$alias} {$company_id} {$locale}";
if (true !== $result = Console::run($command)) {
return [
'success' => false,
'error' => true,
'message' => $result,
'data' => null,
];
}
return [
'success' => true,
'error' => false,
'message' => null,
'data' => [
'name' => $name,
'version' => $version,
],
];
}
public function enableModule($alias)
{
$module = module($alias);
$company_id = session('company_id');
$locale = app()->getLocale();
$command = "module:enable {$alias} {$company_id} {$locale}";
if (true !== $result = Console::run($command)) {
return [
'success' => false,
'error' => true,
'message' => $result,
'data' => null,
];
}
return [
'success' => true,
'error' => false,
'message' => null,
'data' => [
'name' => $module->getName(),
'version' => $module->get('version'),
],
];
}
public function disableModule($alias)
{
$module = module($alias);
$company_id = session('company_id');
$locale = app()->getLocale();
$command = "module:disable {$alias} {$company_id} {$locale}";
if (true !== $result = Console::run($command)) {
return [
'success' => false,
'error' => true,
'message' => $result,
'data' => null,
];
}
return [
'success' => true,
'error' => false,
'message' => null,
'data' => [
'name' => $module->getName(),
'version' => $module->get('version'),
],
];
}
public function moduleExists($alias)
{
if (!module($alias) instanceof \Akaunting\Module\Module) {

View File

@ -1,190 +0,0 @@
<?php
namespace App\Utilities;
use App\Events\Install\UpdateCacheCleared;
use App\Events\Install\UpdateCopied;
use App\Events\Install\UpdateDownloaded;
use App\Events\Install\UpdateUnzipped;
use App\Models\Module\Module;
use App\Utilities\Console;
use App\Traits\SiteApi;
use Cache;
use Date;
use File;
use Illuminate\Support\Str;
use ZipArchive;
class Updater
{
use SiteApi;
public static function clear()
{
Cache::forget('updates');
Cache::forget('versions');
event(new UpdateCacheCleared(session('company_id')));
return true;
}
public static function download($alias, $new, $old)
{
$file = null;
$path = null;
// Check core first
$info = Info::all();
if ($alias == 'core') {
$url = 'core/download/' . $new . '/' . $info['php'] . '/' . $info['mysql'];
} else {
$url = 'apps/' . $alias . '/download/' . $new . '/' . $info['akaunting'] . '/' . $info['api_key'];
}
if (!$response = static::getResponse('GET', $url, ['timeout' => 50, 'track_redirects' => true])) {
throw new \Exception(trans('modules.errors.download', ['module' => $alias]));
}
$file = $response->getBody()->getContents();
$path = 'temp-' . md5(mt_rand());
$temp_path = storage_path('app/temp') . '/' . $path;
$file_path = $temp_path . '/upload.zip';
// Create tmp directory
if (!File::isDirectory($temp_path)) {
File::makeDirectory($temp_path);
}
// Add content to the Zip file
$uploaded = is_int(file_put_contents($file_path, $file)) ? true : false;
if (!$uploaded) {
throw new \Exception(trans('modules.errors.zip', ['module' => $alias]));
}
event(new UpdateDownloaded($alias, $new, $old));
return $path;
}
public static function unzip($path, $alias, $new, $old)
{
$temp_path = storage_path('app/temp') . '/' . $path;
$file = $temp_path . '/upload.zip';
// Unzip the file
$zip = new ZipArchive();
if (($zip->open($file) !== true) || !$zip->extractTo($temp_path)) {
throw new \Exception(trans('modules.errors.unzip', ['module' => $alias]));
}
$zip->close();
// Delete zip file
File::delete($file);
event(new UpdateUnzipped($alias, $new, $old));
return $path;
}
public static function copyFiles($path, $alias, $new, $old)
{
$temp_path = storage_path('app/temp') . '/' . $path;
if ($alias == 'core') {
// Move all files/folders from temp path
if (!File::copyDirectory($temp_path, base_path())) {
throw new \Exception(trans('modules.errors.file_copy', ['module' => $alias]));
}
} else {
if ($module = module($alias)) {
$module_path = $module->getPath();
} else {
$module_path = base_path('modules/' . Str::studly($alias));
}
// Create module directory
if (!File::isDirectory($module_path)) {
File::makeDirectory($module_path);
}
// Move all files/folders from temp path
if (!File::copyDirectory($temp_path, $module_path)) {
throw new \Exception(trans('modules.errors.file_copy', ['module' => $alias]));
}
}
// Delete temp directory
File::deleteDirectory($temp_path);
event(new UpdateCopied($alias, $new, $old));
return $path;
}
public static function finish($alias, $new, $old)
{
if ($alias == 'core') {
$companies = [session('company_id')];
} else {
$companies = Module::alias($alias)->where('company_id', '<>', '0')->pluck('company_id')->toArray();
}
foreach ($companies as $company) {
$command = "update:finish {$alias} {$company} {$new} {$old}";
if (true !== $result = Console::run($command)) {
$message = !empty($result) ? $result : trans('modules.errors.finish', ['module' => $alias]);
throw new \Exception($message);
}
}
}
public static function all()
{
// Get data from cache
$updates = Cache::get('updates');
if (!empty($updates)) {
return $updates;
}
$updates = [];
$modules = module()->all();
$versions = Versions::all($modules);
foreach ($versions as $alias => $latest_version) {
if ($alias == 'core') {
$installed_version = version('short');
} else {
$module = module($alias);
if (!$module instanceof \Akaunting\Module\Module) {
continue;
}
$installed_version = $module->get('version');
}
if (version_compare($installed_version, $latest_version, '>=')) {
continue;
}
$updates[$alias] = $latest_version;
}
Cache::put('updates', $updates, Date::now()->addHour(6));
return $updates;
}
}

View File

@ -105,7 +105,7 @@ class Versions
return $versions;
}
protected static function getLatestVersion($url, $latest)
public static function getLatestVersion($url, $latest)
{
if (!$data = static::getResponseData('GET', $url, ['timeout' => 10])) {
return $latest;
@ -117,4 +117,44 @@ class Versions
return $data->latest;
}
public static function getUpdates()
{
// Get data from cache
$updates = Cache::get('updates');
if (!empty($updates)) {
return $updates;
}
$updates = [];
$modules = module()->all();
$versions = static::all($modules);
foreach ($versions as $alias => $latest_version) {
if ($alias == 'core') {
$installed_version = version('short');
} else {
$module = module($alias);
if (!$module instanceof \Akaunting\Module\Module) {
continue;
}
$installed_version = $module->get('version');
}
if (version_compare($installed_version, $latest_version, '>=')) {
continue;
}
$updates[$alias] = $latest_version;
}
Cache::put('updates', $updates, Date::now()->addHour(6));
return $updates;
}
}