170 lines
5.1 KiB
PHP
170 lines
5.1 KiB
PHP
<?php
|
|
|
|
namespace App\Console\Commands;
|
|
|
|
use Illuminate\Console\Command;
|
|
use Illuminate\Support\Facades\Artisan;
|
|
use Illuminate\Support\Facades\File;
|
|
use App\Models\AddOn;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class InstallCommand extends Command
|
|
{
|
|
protected $signature = 'app:install
|
|
{--force : Force installation even if already installed}';
|
|
|
|
protected $description = 'Install the application';
|
|
|
|
public function handle()
|
|
{
|
|
if ($this->isInstalled() && !$this->option('force')) {
|
|
$this->error('Application is already installed. Use --force to reinstall.');
|
|
return 1;
|
|
}
|
|
|
|
$this->info('Starting application installation...');
|
|
|
|
// Generate app key if not exists
|
|
if (empty(config('app.key'))) {
|
|
$this->info('Generating application key...');
|
|
Artisan::call('key:generate', ['--force' => true]);
|
|
}
|
|
|
|
// Handle foreign key constraints based on database type
|
|
$dbType = config('database.default');
|
|
if ($dbType === 'mysql') {
|
|
DB::statement('SET FOREIGN_KEY_CHECKS=0');
|
|
}
|
|
|
|
// Drop all tables if they exist
|
|
Artisan::call('migrate:fresh', ['--force' => true]);
|
|
|
|
if ($dbType === 'mysql') {
|
|
DB::statement('SET FOREIGN_KEY_CHECKS=1');
|
|
}
|
|
|
|
Artisan::call('db:seed', ['--force' => true]);
|
|
|
|
// Install packages
|
|
$this->installPackages();
|
|
|
|
// Create installed file
|
|
$this->createInstalledFile();
|
|
|
|
$this->info('Application installed successfully!');
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
private function createInstalledFile()
|
|
{
|
|
File::put(storage_path('installed'), 'install ' . date('Y-m-d H:i:s'));
|
|
}
|
|
|
|
private function installPackages()
|
|
{
|
|
$this->info('Installing packages...');
|
|
|
|
try {
|
|
$modules = $this->getAllAvailableModules();
|
|
|
|
foreach ($modules as $module) {
|
|
$this->info("Installing module: {$module['alias']}");
|
|
try {
|
|
$this->enableModule($module['name']);
|
|
$this->info("✓ Module {$module['alias']} installed successfully");
|
|
} catch (\Exception $e) {
|
|
$this->error("✗ Failed to install {$module['alias']}: " . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
$this->info('All packages installed successfully.');
|
|
} catch (\Exception $e) {
|
|
$this->error('Package installation failed: ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
private function getAllAvailableModules()
|
|
{
|
|
$modules = [];
|
|
$packagesPath = base_path('packages/workdo');
|
|
|
|
if (!File::exists($packagesPath)) {
|
|
return $modules;
|
|
}
|
|
|
|
$directories = File::directories($packagesPath);
|
|
|
|
foreach ($directories as $directory) {
|
|
$moduleName = basename($directory);
|
|
$moduleJsonPath = "{$directory}/module.json";
|
|
|
|
if (File::exists($moduleJsonPath)) {
|
|
$moduleData = json_decode(File::get($moduleJsonPath), true);
|
|
if ($moduleData) {
|
|
$modules[] = [
|
|
'name' => $moduleData['name'],
|
|
'alias' => $moduleData['alias'],
|
|
'description' => $moduleData['description'] ?? '',
|
|
'priority' => $moduleData['priority'] ?? 10,
|
|
];
|
|
}
|
|
}
|
|
}
|
|
|
|
usort($modules, function ($a, $b) {
|
|
return $a['priority'] - $b['priority'];
|
|
});
|
|
|
|
return $modules;
|
|
}
|
|
|
|
private function enableModule($moduleName)
|
|
{
|
|
// Validate module name to prevent path traversal
|
|
if (!preg_match('/^[a-zA-Z0-9_-]+$/', $moduleName)) {
|
|
throw new \Exception('Invalid module name');
|
|
}
|
|
|
|
$addon = AddOn::where('module', $moduleName)->first();
|
|
if (empty($addon)) {
|
|
$filePath = base_path('packages/workdo/' . $moduleName . '/module.json');
|
|
|
|
if (!file_exists($filePath)) {
|
|
throw new \Exception('Module configuration not found');
|
|
}
|
|
|
|
$jsonContent = file_get_contents($filePath);
|
|
$data = json_decode($jsonContent, true);
|
|
|
|
if (!$data) {
|
|
throw new \Exception('Invalid module configuration');
|
|
}
|
|
|
|
Artisan::call('package:seed ' . $moduleName);
|
|
|
|
$addon = new AddOn;
|
|
$addon->module = $data['name'];
|
|
$addon->name = $data['alias'];
|
|
$addon->monthly_price = $data['monthly_price'] ?? 0;
|
|
$addon->yearly_price = $data['yearly_price'] ?? 0;
|
|
$addon->package_name = $data['package_name'] ?? null;
|
|
$addon->for_admin = $data['for_admin'] ?? false;
|
|
$addon->priority = $data['priority'] ?? 0;
|
|
$addon->is_enable = 1;
|
|
$addon->save();
|
|
} else {
|
|
|
|
Artisan::call('package:seed ' . $moduleName);
|
|
|
|
$addon->is_enable = 1;
|
|
$addon->save();
|
|
}
|
|
}
|
|
|
|
private function isInstalled(): bool
|
|
{
|
|
return File::exists(storage_path('installed'));
|
|
}
|
|
} |