Skip to content

Commit

Permalink
Merge pull request #43 from johntrickett86/action-make-command
Browse files Browse the repository at this point in the history
Added the missing make:filament-action command
  • Loading branch information
CodeWithDennis authored Nov 1, 2024
2 parents 0070cbc + c291a72 commit 341080c
Show file tree
Hide file tree
Showing 4 changed files with 204 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ Kickstart your project and save time with Larament! This time-saving starter kit
- All component labels are automatically translatable.
- A `composer review` command that runs PINT, PHPStan, and PEST.
- Helper file is included for custom helper functions.
- A custom `php artisan make:filament-action` command is available for creating actions.

### Design
![user-global-search](https://raw.githubusercontent.com/CodeWithDennis/larament/main/resources/images/user-global-search.jpg)
Expand Down
163 changes: 163 additions & 0 deletions app/Console/Commands/MakeFilamentActionCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;

use function Laravel\Prompts\info;
use function Laravel\Prompts\select;
use function Laravel\Prompts\text;
use function Laravel\Prompts\warning;

class MakeFilamentActionCommand extends Command
{
protected $signature = 'make:filament-action {name?}
{--form : Generate a form component action}
{--table : Generate a table component action}
{--table-bulk : Generate a table bulk action}
{--custom-component : Generate a custom component action}
{--infolist : Generate an infolist component action}
{--notification : Generate a notification action}
{--global-search : Generate a global search result action}';

protected $description = 'Create a new Filament action class';

/**
* @var array<string, string>
*/
protected array $actionTypes = [
'form' => 'Filament\\Forms\\Components\\Actions\\Action',
'table' => 'Filament\\Tables\\Actions\\Action',
'table-bulk' => 'Filament\\Tables\\Actions\\BulkAction',
'custom-component' => 'Filament\\Actions\\Action',
'infolist' => 'Filament\\Infolists\\Components\\Actions\\Action',
'notification' => 'Filament\\Notifications\\Actions\\Action',
'global-search' => 'Filament\\GlobalSearch\\Actions\\Action',
];

public function handle(): void
{
$name = $this->getNameArgument();
$className = $this->getClassName($name);
$type = $this->getActionType();
$actionClass = $this->actionTypes[$type];
$baseClass = $type === 'table-bulk' ? 'BulkAction' : 'Action';
$path = $this->getFilePath($className, $type);

if ($this->fileExists($path)) {
warning("$className already exists.");

return;
}

$stubContent = $this->getStubContent();
$this->generateActionFile($path, $className, $actionClass, $stubContent, $baseClass);

info("$className created successfully at:");
info($path);
}

private function getNameArgument(): string
{
return $this->argument('name') ?? text(
label: 'Enter the name of the Filament Action',
required: 'Action name is required.',
);
}

private function getClassName(string $name): string
{
return Str::endsWith(Str::lower($name), 'action')
? Str::studly($name)
: Str::studly($name).'Action';
}

private function getActionType(): string
{
$selectedTypes = array_filter([
'form' => $this->option('form'),
'table' => $this->option('table'),
'table-bulk' => $this->option('table-bulk'),
'custom-component' => $this->option('custom-component'),
'infolist' => $this->option('infolist'),
'notification' => $this->option('notification'),
'global-search' => $this->option('global-search'),
]);

if (count($selectedTypes) > 1) {
warning('Please specify only one action type.');

exit;
}

if (count($selectedTypes) === 0) {
$selectedType = select(
label: 'Please select the type of the Filament Action',
options: [
'form' => 'Form',
'table' => 'Table',
'table-bulk' => 'TableBulk',
'infolist' => 'Infolist',
'notification' => 'Notification',
'global-search' => 'GlobalSearch',
'custom-component' => 'Custom',
]
);

return (string) $selectedType;
}

return (string) key($selectedTypes);
}

private function getFilePath(string $className, string $type): string
{
$subDirectory = match ($type) {
'form' => 'Forms',
'table', 'table-bulk' => 'Tables',
'infolist' => 'Infolists',
'notification' => 'Notifications',
'global-search' => 'GlobalSearch',
'custom-component' => 'Custom',
default => '',
};

return app_path("Filament/Actions/$subDirectory/$className.php");
}

private function fileExists(string $path): bool
{
return File::exists($path);
}

private function getStubContent(): string
{
$stubPath = app_path('Filament/Actions/Stubs/FilamentAction.stub');

return File::get($stubPath);
}

private function generateActionFile(string $path, string $className, string $actionClass, string $stubContent, string $baseClass): void
{
$namespace = $this->getNamespace($path);
$defaultName = Str::camel(Str::replaceLast('Action', '', $className));

$content = str_replace(
['{{ namespace }}', '{{ className }}', '{{ defaultName }}', '{{ actionClass }}', '{{ baseClass }}'],
[$namespace, $className, $defaultName, $actionClass, $baseClass],
$stubContent
);

File::ensureDirectoryExists(dirname($path));
File::put($path, $content);
}

private function getNamespace(string $path): string
{
$relativePath = Str::after($path, app_path().'/');

return 'App\\'.Str::replace('/', '\\', dirname($relativePath));
}
}
20 changes: 20 additions & 0 deletions app/Filament/Actions/GlobalSearch/TestAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace App\Filament\Actions\GlobalSearch;

use Filament\GlobalSearch\Actions\Action;

class TestAction extends Action
{
public static function getDefaultName(): ?string
{
return 'test';
}

protected function setUp(): void
{
parent::setUp();

// TODO: Add your setup logic here
}
}
20 changes: 20 additions & 0 deletions app/Filament/Actions/Stubs/FilamentAction.stub
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace {{ namespace }};

use {{ actionClass }};

class {{ className }} extends {{ baseClass }}
{
public static function getDefaultName(): ?string
{
return '{{ defaultName }}';
}

protected function setUp(): void
{
parent::setUp();

// TODO: Add your setup logic here
}
}

0 comments on commit 341080c

Please sign in to comment.