diff --git a/InstallLaravel.php b/InstallLaravel.php index 5e92183..797af39 100644 --- a/InstallLaravel.php +++ b/InstallLaravel.php @@ -4,14 +4,31 @@ ////////////////////////////// Config Section //////////////////////////// ////////////////////////////////////////////////////////////////////////// +$color = "\033[01;32m"; +$noColor = "\033[0m"; + $packages = [ - "filament/filament", "spatie/laravel-backup", + "spatie/laravel-settings", "spatie/laravel-tags", "spatie/laravel-ray", "spatie/laravel-responsecache", ]; +$packagesFilament = [ + "filament/filament", + "filament/forms", + "filament/notifications", + "filament/tables", + "filament/spatie-laravel-settings-plugin", + "filament/spatie-laravel-tags-plugin", + "filipfonal/filament-log-manager", + "bezhansalleh/filament-shield", + "3x1io/filament-user", + "3x1io/filament-menus", + "ryangjchandler/filament-profile" +]; + $packagesDev = [ "nunomaduro/larastan", "pestphp/pest-plugin-laravel", @@ -22,10 +39,36 @@ $postProcessSteps = [ 'php artisan vendor:publish --provider="Spatie\Backup\BackupServiceProvider"', 'php artisan vendor:publish --provider="Spatie\Tags\TagsServiceProvider" --tag="tags-migrations"', + 'php artisan vendor:publish --provider="Spatie\Tags\TagsServiceProvider" --tag="tags-config"', + 'php artisan vendor:publish --provider="Spatie\LaravelSettings\LaravelSettingsServiceProvider" --tag="migrations"', + 'php artisan vendor:publish --provider="Spatie\LaravelSettings\LaravelSettingsServiceProvider" --tag="settings"', 'php artisan vendor:publish --provider="Spatie\ResponseCache\ResponseCacheServiceProvider"', 'php artisan ray:publish-config', ]; +$postProcessStepsFilament = [ + 'php artisan forms:install', + 'php artisan tables:install', + 'php artisan notifications:install', + 'php artisan vendor:publish --tag=filament-config', + 'php artisan vendor:publish --tag=filament-translations', + 'php artisan vendor:publish --tag=filament-views', + 'php artisan vendor:publish --tag=filament-forms-translations', + 'php artisan vendor:publish --tag=filament-support-translations', + 'php artisan vendor:publish --tag=filament-support-views', + 'php artisan vendor:publish --tag=filament-tables-translations', + 'php artisan vendor:publish --tag=filament-log-manager-config', + 'php artisan vendor:publish --tag=filament-log-manager-translations', + 'php artisan vendor:publish --tag=filament-log-manager-views', + 'php artisan vendor:publish --tag=filament-shield-config', + 'php artisan vendor:publish --tag=filament-shield-translations', + 'php artisan vendor:publish --tag=filament-user-config', + 'php artisan vendor:publish --tag=filament-user-translations', + 'php artisan vendor:publish --tag=filament-profile-views', + 'php artisan livewire:discover', + 'php artisan optimize:clear', +]; + $postProcessFiles = [ 'rector.php' => " "includes: - ./vendor/nunomaduro/larastan/extension.neon @@ -56,17 +100,53 @@ # checkMissingIterableValueType: false\n\n", ]; +$manualSteps = [ + 'Create a database for your new Laravel instance', + 'Edit .env so that the database connection info is correct/complete', + "run {$color}php artisan migrate{$noColor}", + "run {$color}php artisan db:seed{$noColor}", +]; + +$manualStepsFilament = [ + "run {$color}php artisan filament:upgrade{$noColor}", + "run {$color}php artisan make:filament-user{$noColor}", + "run {$color}php artisan shield:install{$noColor}", +]; +$instructions = [ + "You can run self-contained web server for your instance by typing {$color}php artisan serve{$noColor}", + "Laravel docs are available from https://laravel.com/docs/9.x/", +]; +$instructionsFilament = [ + "You can find the filament login screen under /admin", + "Filament docs are available from https://filamentphp.com/docs/2.x/", + "Information on how to use the installed filament plugins, go to https://filamentphp.com/plugins", +]; ////////////////////////////////////////////////////////////////////////// /////////////////////////////// Install Code ///////////////////////////// ////////////////////////////////////////////////////////////////////////// -// Check for targetDir argument +// Check for args $targetDir = $argv[1] ?? null; if (!$targetDir) { - die("Usage: InstallLaravel \n"); + die("Usage: InstallLaravel [--without-filament]\n"); +} +if (file_exists($targetDir)) { + die("Error: {$color}$targetDir{$noColor} already exists\n"); +} +if (strpos($targetDir, '--') === 0) { + die("Usage: InstallLaravel [--without-filament]\n"); +} + +$withFilament = true; +$argv2 = $argv[2] ?? null; +if ($argv2) { + if ($argv2 != '--without-filament') { + die("Usage: InstallLaravel [--without-filament]\n"); + } + $withFilament = false; } @@ -76,45 +156,71 @@ die ("Unable to find a laravel installer\n"); } -// Define colors -$color = "\033[01;32m"; -$noColor = "\033[0m"; // Now install laravel $cmd = "$laravelInstaller --no-interaction new $targetDir"; -// No installer found, use composer without "new" option -if (strpos($laravelInstaller, 'composer') === 0) { - $cmd = "$laravelInstaller --no-interaction $targetDir"; +if (!$cmd) { // No installer found, use composer + $cmd = "composer create-project --prefer-dist laravel/laravel --no-interaction $targetDir"; } print "{$color}Installing Laravel into [$targetDir]{$noColor}\n"; -system($cmd); +$rc = system($cmd); +if (!$rc === false) { + die("System command [$cmd] failed ... exiting\n"); +} -// Install main packages + +// Determine final packagelist +if ($withFilament) { + $packages = array_merge($packages, $packagesFilament); + $postProcessSteps = array_merge($postProcessSteps, $postProcessStepsFilament); + $manualSteps = array_merge($manualSteps, $manualStepsFilament); + $instructions = array_merge($instructions, $instructionsFilament); +} + + +// Change into install dir chdir($targetDir); -$packageList = implode(' ', $packages); -$cmd = "composer --no-interaction require $packageList"; -print "{$color}Executing [$cmd]{$noColor}\n"; -system($cmd); + + +// Install main packages +$cmd = "composer --no-interaction require " . implode(' ', $packages); +execSteps($cmd, $color, $noColor); // Install dev packages -$packageList = implode(' ', $packagesDev); -$cmd = "composer --no-interaction require $packageList --dev"; -print "{$color}Executing [$cmd]{$noColor}\n"; -system($cmd); +$cmd = "composer --no-interaction --dev require " . implode(' ', $packagesDev); +execSteps($cmd, $color, $noColor); // Execute post process steps -foreach ($postProcessSteps as $step) { - print "{$color}Executing [$step]{$noColor}\n"; - system($step); -} +execSteps($postProcessSteps, $color, $noColor); // Create post process files foreach ($postProcessFiles as $k => $v) { - print "{$color}Creating [$k]{$noColor}\n"; + print "Creating {$color}[$k]{$noColor}\n"; file_put_contents($k, $v); } -print "All done ...\n"; +// Patch user model for filament shield +if (in_array("bezhansalleh/filament-shield", $packages)) { + patchFilamentConfigForDarkMode($color, $noColor); + patchUserModelForFilamentShield($color, $noColor); +} + + +print "\n"; +print "---------------------------------------------\n"; +print "All done ... {$color}now perform these manual steps:{$noColor}\n"; +print "---------------------------------------------\n\n"; +foreach ($manualSteps as $k => $v) { + $kk = $k + 1; + print "$kk) $v\n"; +} +print "\nSome hints to get you started:\n\n"; +foreach ($instructions as $k => $v) { + $kk = $k + 1; + print "$kk) $v\n"; +} + +print "\nNow go build something {$color}awesome!{$noColor}\n\n"; ////////////////////////////////////////////////////////////////////////// @@ -149,6 +255,19 @@ function commandExists($command): bool } +function execSteps(mixed $steps, string $color, string $noColor): void +{ + $steps = (array)$steps; + foreach ($steps as $step) { + print "Executing {$color}$step{$noColor}\n"; + $rc = system($step); + if ($rc === false) { + throw new \Exception("Command [$step] returned an error"); + } + } +} + + function findLaravelInstaller(): string|false { $homeDir = getHomeDirectory(); @@ -158,7 +277,6 @@ function findLaravelInstaller(): string|false "$homeDir/bin/laravel", "$homeDir/.composer/vendor/bin/laravel", "$homeDir/.config/composer/vendor/bin/laravel", - "composer create-project --prefer-dist laravel/laravel", ]; foreach ($installerCommands as $installerCommand) { @@ -181,3 +299,61 @@ function getHomeDirectory(): string return posix_getpwuid(getmyuid())['dir']; } + +function patchFilamentConfigForDarkMode(string $color, string $noColor): void +{ + $configFile = "config/filament.php"; + print "Patching {$color}$configFile{$noColor} to enable darkMode\n"; + + $fileData = file_get_contents($configFile); + if (!$fileData) { + throw new \Exception("Unable to read [$configFile]"); + } + $fileLines = explode("\n", $fileData); + $output = []; + + foreach ($fileLines as $line) { + if (strpos($line, "'dark_mode' => false")) { + $line = str_replace('false', 'true', $line); + } + $output[] = $line; + } + + $rc = file_put_contents($configFile, implode("\n", $output)); + if ($rc === false) { + throw new \Exception("Unable to write [$configFile]"); + } +} + + +function patchUserModelForFilamentShield(string $color, string $noColor): void +{ + $userModel = "app/Models/User.php"; + print "Patching {$color}$userModel{$noColor} for use with FilamentShield\n"; + + $fileData = file_get_contents($userModel); + if (!$fileData) { + throw new \Exception("Unable to read [$userModel]"); + } + $fileLines = explode("\n", $fileData); + $output = []; + + $firstUse = false; + $firstBrace = false; + foreach ($fileLines as $line) { + $output[] = $line; + if (!$firstUse && strpos($line, 'use ') === 0) { + $output[] = 'use Spatie\\Permission\\Traits\\HasRoles;'; + $firstUse = true; + } + if (!$firstBrace && strpos($line, '{') === 0) { + $output[] = " use HasRoles;"; + $firstBrace = true; + } + } + + $rc = file_put_contents($userModel, implode("\n", $output)); + if ($rc === false) { + throw new \Exception("Unable to write [$userModel]"); + } +} diff --git a/README.md b/README.md index da686bb..38c5827 100644 --- a/README.md +++ b/README.md @@ -5,14 +5,26 @@ An easily configurable PHP script to install laravel with extra modules and post ## What it does If you do a lot of experimentation with Laravel, this script can save you some time. It allows you (in the top section of the script), to configure packages you want to install (both prod and dev) -as well as some post-install actions and files to create. +as well as some post-install actions and files to create. It also performs some additional actions +such as publishing package config files, migrations, resources, etc. and patches some files so that +everything is set up correctly. Out of the box, it installs the following packages for prod: -- filament/filament - spatie/laravel-backup - patie/laravel-tags - spatie/laravel-ray - spatie/laravel-responsecache +- filament/filament +- filament/forms +- filament/notifications +- filament/tables +- filament/spatie-laravel-settings-plugin +- filament/spatie-laravel-tags-plugin +- filipfonal/filament-log-manager +- bezhansalleh/filament-shield +- 3x1io/filament-user +- 3x1io/filament-menus +- ryangjchandler/filament-profile For dev, it installs the following: - nunomaduro/larastan, @@ -20,23 +32,25 @@ For dev, it installs the following: - laravel/pint - rector/rector -It then publishes any suggested config files for the above packages and creates the following files: +It also creates the following files: - rector.php - phpstan.neon ## Who is it for -It's for Laravel developers. If you know PHP, the script should be self explanatory, if you don't +It's for Laravel developers who quickly want to install a new instance of Laravel and have some manual +steps taken care of automatically. If you know PHP, the script should be self explanatory, if you don't know PHP, this is probably not for you. I wrote it for my own purposes during a weekend of -experimentation. +experimentation (it's a bit hacky but does the job). ## How to use it Assuming you've configured packages you want to install in the top section of the script, you can then call ``` -php InstallLaravel.php +php InstallLaravel.php [--without-filament] ``` -and it will install the latest laravel with the configured packages and actions. +and it will install the latest laravel with the configured packages (ie: with or without filament) and actions. ### Requirements - Written against a PHP8.1 installation, should also work on PHP8.0. - Requires either the Laravel installer or composer to be installed. +