Skip to content

Commit 88ad63b

Browse files
wip installer
1 parent 6ff670c commit 88ad63b

File tree

6 files changed

+129
-37
lines changed

6 files changed

+129
-37
lines changed

packages/core/config/moox-installer.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
// 'require_confirmation' => true,
4141
// ],
4242

43+
4344
'plugins' => [
4445
'enabled' => true,
4546
'priority' => 100,

packages/core/src/Installer/AbstractAssetInstaller.php

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use Illuminate\Support\Facades\Artisan;
77
use Illuminate\Support\Facades\File;
88
use Moox\Core\Installer\Contracts\AssetInstallerInterface;
9+
use Symfony\Component\Console\Input\StringInput;
910

1011
use function Moox\Prompts\multiselect;
1112
use function Moox\Prompts\note;
@@ -270,18 +271,36 @@ protected function publishPackageAssets(string $packageName, string $type, ?stri
270271
$published = false;
271272
foreach ($tags as $tag) {
272273
try {
273-
$result = Artisan::call('vendor:publish', [
274-
'--tag' => $tag,
275-
'--force' => $this->config['force'] ?? false,
276-
]);
277-
278-
$output = trim(Artisan::output());
279-
280-
if ($result === 0 && ! str_contains($output, 'Nothing to publish')) {
281-
$published = true;
282-
break;
274+
// Verwende $this->command->call() wenn verfügbar (nach Prompts funktioniert das besser)
275+
// Das nutzt den korrekten IO-Context vom Command
276+
if ($this->command) {
277+
$result = $this->command->call('vendor:publish', [
278+
'--tag' => $tag,
279+
'--force' => $this->config['force'] ?? false,
280+
]);
281+
282+
// Bei $this->command->call() gibt es keine separate output() Methode
283+
// Die Ausgabe wird direkt angezeigt
284+
if ($result === 0) {
285+
$published = true;
286+
break;
287+
}
283288
} else {
284-
note($output);
289+
// Fallback: Direkt über Application mit sauberem IO-Context
290+
$commandString = 'vendor:publish --tag='.escapeshellarg($tag);
291+
if ($this->config['force'] ?? false) {
292+
$commandString .= ' --force';
293+
}
294+
295+
$input = new StringInput($commandString);
296+
// Wichtig: Als interaktiv markieren, damit Prompts funktionieren
297+
$input->setInteractive(true);
298+
$result = app()->handleCommand($input);
299+
300+
if ($result === 0) {
301+
$published = true;
302+
break;
303+
}
285304
}
286305
} catch (\Exception $e) {
287306
continue;

packages/core/src/Installer/Installers/MigrationInstaller.php

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Illuminate\Support\Facades\Artisan;
66
use Illuminate\Support\Facades\File;
77
use Moox\Core\Installer\AbstractAssetInstaller;
8+
use Symfony\Component\Console\Input\StringInput;
89

910
use function Moox\Prompts\info;
1011
use function Moox\Prompts\note;
@@ -144,11 +145,19 @@ protected function runMigrations(): void
144145
{
145146
try {
146147
info('🔄 Running migrations...');
147-
Artisan::call('migrate', ['--force' => true]);
148-
$output = trim(Artisan::output());
149-
if (! empty($output)) {
150-
note($output);
148+
149+
// Verwende $this->command->call() wenn verfügbar (nach Prompts funktioniert das besser)
150+
// Das nutzt den korrekten IO-Context vom Command
151+
if ($this->command) {
152+
$this->command->call('migrate', ['--force' => true]);
153+
} else {
154+
// Fallback: Direkt über Application mit sauberem IO-Context
155+
$input = new StringInput('migrate --force');
156+
// Wichtig: Als interaktiv markieren, damit Prompts funktionieren
157+
$input->setInteractive(true);
158+
app()->handleCommand($input);
151159
}
160+
152161
info('✅ Migrations executed successfully');
153162
} catch (\Exception $e) {
154163
warning("⚠️ Migration error: {$e->getMessage()}");

packages/core/src/Installer/Installers/PluginInstaller.php

Lines changed: 62 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,21 @@
22

33
namespace Moox\Core\Installer\Installers;
44

5-
use Filament\Support\Commands\Concerns\CanGeneratePanels;
6-
use Filament\Support\Commands\Concerns\CanManipulateFiles;
7-
use Illuminate\Support\Facades\Artisan;
8-
use Illuminate\Support\Facades\File;
9-
use Moox\Core\Installer\AbstractAssetInstaller;
10-
use Moox\Core\Installer\Contracts\PanelAwareInstallerInterface;
11-
12-
use function Moox\Prompts\confirm;
135
use function Moox\Prompts\info;
14-
use function Moox\Prompts\multiselect;
156
use function Moox\Prompts\note;
16-
use function Moox\Prompts\select;
177
use function Moox\Prompts\text;
8+
use function Moox\Prompts\select;
9+
use function Moox\Prompts\confirm;
10+
1811
use function Moox\Prompts\warning;
12+
use Illuminate\Support\Facades\File;
13+
use function Moox\Prompts\multiselect;
14+
use Illuminate\Support\Facades\Artisan;
15+
use Moox\Core\Installer\AbstractAssetInstaller;
16+
use Symfony\Component\Console\Input\StringInput;
17+
use Filament\Support\Commands\Concerns\CanGeneratePanels;
18+
use Filament\Support\Commands\Concerns\CanManipulateFiles;
19+
use Moox\Core\Installer\Contracts\PanelAwareInstallerInterface;
1920

2021
/**
2122
* Installer for Filament plugins.
@@ -265,18 +266,61 @@ protected function createNewPanel(): ?string
265266
required: true
266267
);
267268

269+
// Sanitize panel name - only allow alphanumeric and hyphens
270+
$panelName = preg_replace('/[^a-zA-Z0-9-]/', '', $panelName);
271+
272+
if (empty($panelName)) {
273+
warning('Invalid panel name');
274+
return null;
275+
}
276+
277+
$filamentPath = app_path('Providers/Filament');
278+
if (! File::isDirectory($filamentPath)) {
279+
File::makeDirectory($filamentPath, 0755, true);
280+
}
281+
282+
$className = ucfirst($panelName).'PanelProvider';
283+
$expectedPath = $filamentPath.'/'.$className.'.php';
284+
268285
try {
269-
Artisan::call('make:filament-panel', [
270-
'id' => $panelName,
271-
'--force' => true,
272-
]);
273-
} catch (FailureCommandOutput) {
274-
warning("Failed to create panel: {$panelName}");
286+
// Verwende $this->command->call() wenn verfügbar (nach Prompts funktioniert das besser)
287+
// Das nutzt den korrekten IO-Context vom Command
288+
if ($this->command) {
289+
$exitCode = $this->command->call('make:filament-panel', [
290+
'id' => $panelName,
291+
'--force' => File::exists($expectedPath),
292+
]);
293+
} else {
294+
// Fallback: Direkt über Application mit sauberem IO-Context
295+
// Das umgeht das Problem mit dem veränderten IO-Context nach Prompts
296+
$commandString = 'make:filament-panel '.$panelName;
297+
if (File::exists($expectedPath)) {
298+
$commandString .= ' --force';
299+
}
300+
301+
$input = new StringInput($commandString);
302+
// Wichtig: Als interaktiv markieren, damit Prompts funktionieren
303+
$input->setInteractive(true);
304+
$exitCode = app()->handleCommand($input);
305+
}
306+
307+
if ($exitCode !== 0) {
308+
warning("⚠️ Panel konnte nicht erstellt werden (Exit Code: {$exitCode})");
309+
return null;
310+
}
275311

312+
// Prüfen ob die Datei erstellt wurde
313+
if (File::exists($expectedPath)) {
314+
note("✅ Panel created: {$panelName}");
315+
return $expectedPath;
316+
}
317+
318+
warning('Panel creation may have failed - file not found');
319+
return null;
320+
} catch (\Throwable $e) {
321+
warning("Could not create panel: {$e->getMessage()}");
276322
return null;
277323
}
278-
279-
return $panelName;
280324
}
281325

282326
protected function registerPluginsInPanel(array $pluginClasses, string $panelPath): void

packages/core/src/Installer/Installers/SeederInstaller.php

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Illuminate\Support\Facades\Artisan;
66
use Moox\Core\Installer\AbstractAssetInstaller;
7+
use Symfony\Component\Console\Input\StringInput;
78

89
use function Moox\Prompts\confirm;
910
use function Moox\Prompts\info;
@@ -89,10 +90,21 @@ public function install(array $assets): bool
8990
try {
9091
$seederClass = $this->resolveSeederClass($packageName, $seeder);
9192
if ($seederClass && class_exists($seederClass)) {
92-
Artisan::call('db:seed', [
93-
'--class' => $seederClass,
94-
'--force' => true,
95-
]);
93+
// Verwende $this->command->call() wenn verfügbar (nach Prompts funktioniert das besser)
94+
// Das nutzt den korrekten IO-Context vom Command
95+
if ($this->command) {
96+
$this->command->call('db:seed', [
97+
'--class' => $seederClass,
98+
'--force' => true,
99+
]);
100+
} else {
101+
// Fallback: Direkt über Application mit sauberem IO-Context
102+
$commandString = 'db:seed --class='.escapeshellarg($seederClass).' --force';
103+
$input = new StringInput($commandString);
104+
// Wichtig: Als interaktiv markieren, damit Prompts funktionieren
105+
$input->setInteractive(true);
106+
app()->handleCommand($input);
107+
}
96108
note("{$seeder}: Executed");
97109
$executed++;
98110
} else {

packages/core/src/Installer/Traits/HasInstallationHooks.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,13 @@ protected function runWithHooks(InstallerRegistry $registry, array $assets, arra
101101
}
102102

103103
$this->beforeInstaller($type);
104+
105+
// Setze das Command-Objekt, damit Installer $this->command->call() verwenden können
106+
// Das ist wichtig, damit der IO-Context nach Prompts korrekt funktioniert
107+
if (method_exists($installer, 'setCommand')) {
108+
$installer->setCommand($this);
109+
}
110+
104111
$installer->install($typeAssets);
105112
$this->afterInstaller($type);
106113
} catch (\Exception $e) {

0 commit comments

Comments
 (0)