From 4d1175b874c5d899177c32a76ce240d11418c8a7 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Tue, 3 Dec 2024 22:33:49 -0500 Subject: [PATCH 01/24] Add new `starter-kit:init` command. --- src/Console/Commands/StarterKitInit.php | 162 ++++++++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 src/Console/Commands/StarterKitInit.php diff --git a/src/Console/Commands/StarterKitInit.php b/src/Console/Commands/StarterKitInit.php new file mode 100644 index 00000000000..5ca17b19a84 --- /dev/null +++ b/src/Console/Commands/StarterKitInit.php @@ -0,0 +1,162 @@ +getKitName(); + $description = $this->getKitDescription(); + $package = $this->getKitPackage(); + + if (! $name || ! $package || ! $description) { + $this->components->info('You can manage your starter kit\'s package config in [package/composer.json] at any time.'); + } + + $this + ->createFolder() + // ->migrateLegacy() // TODO: Consolidate logic to trait from other PR + ->createConfig() + ->createComposerJson($name, $description, $package); + + $this->components->success('Starter kit config was successfully created in [package/] folder.'); + } + + /** + * Get starter kit name for composer.json (optional). + */ + protected function getKitName(): ?string + { + return $this->argument('name') ?: text('Starter Kit Name'); + } + + /** + * Get starter kit description for composer.json (optional). + */ + protected function getKitDescription(): ?string + { + return $this->argument('description') ?: text('Starter Kit Description'); + } + + /** + * Get starter kit package for composer.json (optional). + */ + protected function getKitPackage(bool $promptingAgain = false): ?string + { + $promptText = 'Starter Kit Package (eg. hasselhoff/kung-fury)'; + + if ($promptingAgain) { + $package = text($promptText); + } else { + $package = $this->argument('package') ?: text($promptText); + } + + $fails = $this->validationFails($package, new ComposerPackage); + + if ($package && $fails && $this->input->isInteractive()) { + return $this->getKitPackage(true); + } elseif ($package && $fails) { + return null; + } + + return $package; + } + + /** + * Create composer.json config from stub. + */ + protected function createFolder(): self + { + if (! File::exists($dir = base_path('package'))) { + File::makeDirectory($dir, 0755, true); + } + + return $this; + } + + /** + * Create starter-kit.yaml config from stub. + */ + protected function createConfig(): self + { + $contents = File::get(__DIR__.'/stubs/starter-kits/starter-kit.yaml.stub'); + + $targetPath = base_path('package/starter-kit.yaml'); + + if (File::exists($targetPath) && $this->input->isInteractive()) { + if (! confirm('A [starter-kit.yaml] config already exists. Would you like to overwrite it?', false)) { + return $this; + } + } + + // TODO: Ask if updatable, and if so prepend `updatable: true` to yaml and create service provider too? + + File::put($targetPath, $contents); + + return $this; + } + + /** + * Create composer.json config from stub. + */ + protected function createComposerJson(?string $name, ?string $description, ?string $package): self + { + $contents = File::get(__DIR__.'/stubs/starter-kits/composer.json.stub'); + + $targetPath = base_path('package/composer.json'); + + if (File::exists($targetPath) && $this->input->isInteractive()) { + if (! confirm('A [composer.json] config already exists. Would you like to overwrite it?', false)) { + return $this; + } + } + + if ($name) { + $contents = str_replace('Example Name', $name, $contents); + } + + if ($description) { + $contents = str_replace('A description of your starter kit', $description, $contents); + } + + if ($package) { + $contents = str_replace('example/starter-kit-package', $package, $contents); + } + + File::put($targetPath, $contents); + + return $this; + } +} From 40b8600b8d555f8af52e54b96c19ba0e636a2728 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Tue, 3 Dec 2024 22:33:55 -0500 Subject: [PATCH 02/24] Register command. --- src/Providers/ConsoleServiceProvider.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Providers/ConsoleServiceProvider.php b/src/Providers/ConsoleServiceProvider.php index 75c3bf1fabd..4a043e0ac46 100644 --- a/src/Providers/ConsoleServiceProvider.php +++ b/src/Providers/ConsoleServiceProvider.php @@ -36,6 +36,7 @@ class ConsoleServiceProvider extends ServiceProvider Commands\StacheWarm::class, Commands\StacheDoctor::class, Commands\StarterKitExport::class, + Commands\StarterKitInit::class, Commands\StarterKitInstall::class, Commands\StarterKitRunPostInstall::class, Commands\StaticClear::class, From 72eca0680a82c7ccb0ac90dcdcc5a77d0f2e8e1e Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Tue, 3 Dec 2024 22:34:03 -0500 Subject: [PATCH 03/24] Update stub. --- src/Console/Commands/stubs/starter-kits/composer.json.stub | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Console/Commands/stubs/starter-kits/composer.json.stub b/src/Console/Commands/stubs/starter-kits/composer.json.stub index beeb294312c..627d3f2ea24 100644 --- a/src/Console/Commands/stubs/starter-kits/composer.json.stub +++ b/src/Console/Commands/stubs/starter-kits/composer.json.stub @@ -1,9 +1,9 @@ { - "name": "dummy/package", + "name": "example/starter-kit-package", "extra": { "statamic": { - "name": "DummyTitle", - "description": "DummyTitle starter kit" + "name": "Example Name", + "description": "A description of your starter kit" } } } From 2faa54f309324c0ed25e75599b333a8c16ca1961 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Tue, 3 Dec 2024 22:34:42 -0500 Subject: [PATCH 04/24] Clean up other commands a bit to match this one. --- src/Console/Commands/StarterKitExport.php | 2 +- src/Console/Commands/StarterKitInstall.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Console/Commands/StarterKitExport.php b/src/Console/Commands/StarterKitExport.php index 3545c1e7439..3c852700438 100644 --- a/src/Console/Commands/StarterKitExport.php +++ b/src/Console/Commands/StarterKitExport.php @@ -55,7 +55,7 @@ public function handle() return 1; } - $this->components->info("Starter kit was successfully exported to [$path]."); + $this->components->success("Starter kit was successfully exported to [$path]."); } /** diff --git a/src/Console/Commands/StarterKitInstall.php b/src/Console/Commands/StarterKitInstall.php index cf3864745a2..4a422dc86de 100644 --- a/src/Console/Commands/StarterKitInstall.php +++ b/src/Console/Commands/StarterKitInstall.php @@ -49,7 +49,7 @@ public function handle() [$package, $branch] = $this->getPackageAndBranch(); if ($this->validationFails($package, new ComposerPackage)) { - return; + return 1; } $licenseManager = StarterKitLicenseManager::validate($package, $this->option('license'), $this, $this->input->isInteractive()); @@ -90,7 +90,7 @@ public function handle() $this->comment('composer global update statamic/cli'.PHP_EOL); } - $this->components->info("Starter kit [$package] was successfully installed."); + $this->components->success("Starter kit [$package] was successfully installed."); } /** From d81e06ca803d6d2d157c18f469180bab3ca28017 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Tue, 3 Dec 2024 22:56:48 -0500 Subject: [PATCH 05/24] =?UTF-8?q?Make=20`=E2=80=94name`=20and=20`=E2=80=94?= =?UTF-8?q?description`=20options=20instead=20of=20args,=20since=20they?= =?UTF-8?q?=E2=80=99re=20just=20meta.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Console/Commands/StarterKitInit.php | 56 ++++++++++++------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/src/Console/Commands/StarterKitInit.php b/src/Console/Commands/StarterKitInit.php index 5ca17b19a84..6b5a75cf23d 100644 --- a/src/Console/Commands/StarterKitInit.php +++ b/src/Console/Commands/StarterKitInit.php @@ -21,9 +21,9 @@ class StarterKitInit extends Command * @var string */ protected $signature = 'statamic:starter-kit:init - { name? : Specify a name for the starter kit } - { description? : Specify a description of the starter kit } - { package? : Specify a package for the starter kit (ie. vendor/starter-kit) }'; + { package? : Specify a package for the starter kit (ie. vendor/starter-kit) } + { --name : Specify a name for the starter kit } + { --description : Specify a description of the starter kit }'; /** * The console command description. @@ -37,11 +37,11 @@ class StarterKitInit extends Command */ public function handle() { + $package = $this->getKitPackage(); $name = $this->getKitName(); $description = $this->getKitDescription(); - $package = $this->getKitPackage(); - if (! $name || ! $package || ! $description) { + if (! $package || ! $name || ! $description) { $this->components->info('You can manage your starter kit\'s package config in [package/composer.json] at any time.'); } @@ -49,25 +49,9 @@ public function handle() ->createFolder() // ->migrateLegacy() // TODO: Consolidate logic to trait from other PR ->createConfig() - ->createComposerJson($name, $description, $package); + ->createComposerJson($package, $name, $description); - $this->components->success('Starter kit config was successfully created in [package/] folder.'); - } - - /** - * Get starter kit name for composer.json (optional). - */ - protected function getKitName(): ?string - { - return $this->argument('name') ?: text('Starter Kit Name'); - } - - /** - * Get starter kit description for composer.json (optional). - */ - protected function getKitDescription(): ?string - { - return $this->argument('description') ?: text('Starter Kit Description'); + $this->components->success('Your starter kit config was successfully created in your project\'s [package] folder.'); } /** @@ -94,6 +78,22 @@ protected function getKitPackage(bool $promptingAgain = false): ?string return $package; } + /** + * Get starter kit name for composer.json (optional). + */ + protected function getKitName(): ?string + { + return $this->option('name') ?: text('Starter Kit Name (eg. Kung Fury)'); + } + + /** + * Get starter kit description for composer.json (optional). + */ + protected function getKitDescription(): ?string + { + return $this->option('description') ?: text('Starter Kit Description'); + } + /** * Create composer.json config from stub. */ @@ -131,7 +131,7 @@ protected function createConfig(): self /** * Create composer.json config from stub. */ - protected function createComposerJson(?string $name, ?string $description, ?string $package): self + protected function createComposerJson(?string $package, ?string $name, ?string $description): self { $contents = File::get(__DIR__.'/stubs/starter-kits/composer.json.stub'); @@ -143,6 +143,10 @@ protected function createComposerJson(?string $name, ?string $description, ?stri } } + if ($package) { + $contents = str_replace('example/starter-kit-package', $package, $contents); + } + if ($name) { $contents = str_replace('Example Name', $name, $contents); } @@ -151,10 +155,6 @@ protected function createComposerJson(?string $name, ?string $description, ?stri $contents = str_replace('A description of your starter kit', $description, $contents); } - if ($package) { - $contents = str_replace('example/starter-kit-package', $package, $contents); - } - File::put($targetPath, $contents); return $this; From 9b915ab187d05b7e89626c0b76e5e010b2c581ce Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Wed, 4 Dec 2024 12:43:45 -0500 Subject: [PATCH 06/24] Extract this out so it can be reused by `init` command. --- .../MigratesLegacyStarterKitConfig.php | 55 +++++++++++++++++++ src/Console/Commands/StarterKitExport.php | 46 +--------------- 2 files changed, 58 insertions(+), 43 deletions(-) create mode 100644 src/Console/Commands/Concerns/MigratesLegacyStarterKitConfig.php diff --git a/src/Console/Commands/Concerns/MigratesLegacyStarterKitConfig.php b/src/Console/Commands/Concerns/MigratesLegacyStarterKitConfig.php new file mode 100644 index 00000000000..3dd0a4e2b0a --- /dev/null +++ b/src/Console/Commands/Concerns/MigratesLegacyStarterKitConfig.php @@ -0,0 +1,55 @@ +isUsingLegacyExporterConventions()) { + return $this; + } + + if ($this->input->isInteractive()) { + if (! confirm('Config should now live in the [package] folder. Would you like Statamic to move it for you?', true)) { + return $this; + } + } + + if (! File::exists($dir = base_path('package'))) { + File::makeDirectory($dir, 0755, true); + } + + if (File::exists($starterKitConfig = base_path('starter-kit.yaml'))) { + File::move($starterKitConfig, base_path('package/starter-kit.yaml')); + $this->components->info('Starter kit config moved to [package/starter-kit.yaml].'); + } + + if (File::exists($postInstallHook = base_path('StarterKitPostInstall.php'))) { + File::move($postInstallHook, base_path('package/StarterKitPostInstall.php')); + $this->components->info('Starter kit post-install hook moved to [package/StarterKitPostInstall.php].'); + } + + if (File::exists($packageComposerJson = $this->getAbsolutePath().'/composer.json')) { + File::move($packageComposerJson, base_path('package/composer.json')); + $this->components->info('Composer package config moved to [package/composer.json].'); + } + + return $this; + } +} diff --git a/src/Console/Commands/StarterKitExport.php b/src/Console/Commands/StarterKitExport.php index 958348061a1..5838963e2b4 100644 --- a/src/Console/Commands/StarterKitExport.php +++ b/src/Console/Commands/StarterKitExport.php @@ -3,6 +3,7 @@ namespace Statamic\Console\Commands; use Illuminate\Console\Command; +use Statamic\Console\Commands\Concerns\MigratesLegacyStarterKitConfig; use Statamic\Console\RunsInPlease; use Statamic\Facades\File; use Statamic\Facades\Path; @@ -13,7 +14,7 @@ class StarterKitExport extends Command { - use RunsInPlease; + use MigratesLegacyStarterKitConfig, RunsInPlease; /** * The name and signature of the console command. @@ -36,9 +37,7 @@ class StarterKitExport extends Command */ public function handle() { - if ($this->isUsingLegacyExporterConventions()) { - $this->askToMigrateToPackageFolder(); - } + $this->migrateLegacyStarterKitConfig(); if (! File::exists($path = $this->getAbsolutePath())) { $this->askToCreateExportPath($path); @@ -85,43 +84,4 @@ protected function askToCreateExportPath(string $path): void $this->components->info("A new directory has been created at [{$path}]."); } - - /** - * Determine if dev sandbox has starter-kit.yaml at root and/or customized composer.json at target path. - */ - protected function isUsingLegacyExporterConventions(): bool - { - return File::exists(base_path('starter-kit.yaml')); - } - - /** - * Determine if dev sandbox has starter-kit.yaml at root and/or customized composer.json at target path. - */ - protected function askToMigrateToPackageFolder(): void - { - if ($this->input->isInteractive()) { - if (! confirm('Config should now live in the [package] folder. Would you like Statamic to move it for you?', true)) { - return; - } - } - - if (! File::exists($dir = base_path('package'))) { - File::makeDirectory($dir, 0755, true); - } - - if (File::exists($starterKitConfig = base_path('starter-kit.yaml'))) { - File::move($starterKitConfig, base_path('package/starter-kit.yaml')); - $this->components->info('Starter kit config moved to [package/starter-kit.yaml].'); - } - - if (File::exists($postInstallHook = base_path('StarterKitPostInstall.php'))) { - File::move($postInstallHook, base_path('package/StarterKitPostInstall.php')); - $this->components->info('Starter kit post-install hook moved to [package/StarterKitPostInstall.php].'); - } - - if (File::exists($packageComposerJson = $this->getAbsolutePath().'/composer.json')) { - File::move($packageComposerJson, base_path('package/composer.json')); - $this->components->info('Composer package config moved to [package/composer.json].'); - } - } } From 8df346df52e71129b897696147546e1b981537e4 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Wed, 4 Dec 2024 12:56:53 -0500 Subject: [PATCH 07/24] Make it runnable without export path. --- .../Concerns/MigratesLegacyStarterKitConfig.php | 16 ++++++++++++++-- src/Console/Commands/StarterKitExport.php | 6 ++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/Console/Commands/Concerns/MigratesLegacyStarterKitConfig.php b/src/Console/Commands/Concerns/MigratesLegacyStarterKitConfig.php index 3dd0a4e2b0a..4f2cb34b142 100644 --- a/src/Console/Commands/Concerns/MigratesLegacyStarterKitConfig.php +++ b/src/Console/Commands/Concerns/MigratesLegacyStarterKitConfig.php @@ -8,6 +8,8 @@ trait MigratesLegacyStarterKitConfig { + protected $migrated = false; + /** * Determine if dev sandbox has starter-kit.yaml at root and/or customized composer.json at target path. */ @@ -19,7 +21,7 @@ protected function isUsingLegacyExporterConventions(): bool /** * Determine if dev sandbox has starter-kit.yaml at root and/or customized composer.json at target path. */ - protected function migrateLegacyStarterKitConfig(): self + protected function migrateLegacyConfig(?string $exportPath = null): self { if (! $this->isUsingLegacyExporterConventions()) { return $this; @@ -45,11 +47,21 @@ protected function migrateLegacyStarterKitConfig(): self $this->components->info('Starter kit post-install hook moved to [package/StarterKitPostInstall.php].'); } - if (File::exists($packageComposerJson = $this->getAbsolutePath().'/composer.json')) { + if ($exportPath && File::exists($packageComposerJson = $exportPath.'/composer.json')) { File::move($packageComposerJson, base_path('package/composer.json')); $this->components->info('Composer package config moved to [package/composer.json].'); } + $this->migrated = true; + return $this; } + + /** + * Check if migration logic was ran. + */ + protected function migratedLegacyConfig(): bool + { + return $this->migrated; + } } diff --git a/src/Console/Commands/StarterKitExport.php b/src/Console/Commands/StarterKitExport.php index 5838963e2b4..e93969ddcd0 100644 --- a/src/Console/Commands/StarterKitExport.php +++ b/src/Console/Commands/StarterKitExport.php @@ -37,9 +37,11 @@ class StarterKitExport extends Command */ public function handle() { - $this->migrateLegacyStarterKitConfig(); + $path = $this->getAbsolutePath(); - if (! File::exists($path = $this->getAbsolutePath())) { + $this->migrateLegacyConfig($path); + + if (! File::exists($path)) { $this->askToCreateExportPath($path); } From d7d933379c168d85f3ee62e8d8c38493a514050a Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Wed, 4 Dec 2024 12:58:15 -0500 Subject: [PATCH 08/24] Implement legacy config migration in `init`. --- src/Console/Commands/StarterKitInit.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Console/Commands/StarterKitInit.php b/src/Console/Commands/StarterKitInit.php index 6b5a75cf23d..ccadb9ed9e9 100644 --- a/src/Console/Commands/StarterKitInit.php +++ b/src/Console/Commands/StarterKitInit.php @@ -3,6 +3,7 @@ namespace Statamic\Console\Commands; use Illuminate\Console\Command; +use Statamic\Console\Commands\Concerns\MigratesLegacyStarterKitConfig; use Statamic\Console\RunsInPlease; use Statamic\Console\ValidatesInput; use Statamic\Facades\File; @@ -13,7 +14,7 @@ class StarterKitInit extends Command { - use RunsInPlease, ValidatesInput; + use MigratesLegacyStarterKitConfig, RunsInPlease, ValidatesInput; /** * The name and signature of the console command. @@ -46,8 +47,8 @@ public function handle() } $this + ->migrateLegacyConfig() ->createFolder() - // ->migrateLegacy() // TODO: Consolidate logic to trait from other PR ->createConfig() ->createComposerJson($package, $name, $description); @@ -111,6 +112,10 @@ protected function createFolder(): self */ protected function createConfig(): self { + if ($this->migratedLegacyConfig()) { + return $this; + } + $contents = File::get(__DIR__.'/stubs/starter-kits/starter-kit.yaml.stub'); $targetPath = base_path('package/starter-kit.yaml'); From ecf04429e6e4b20c51af1ff1c0a877ae20886842 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Wed, 4 Dec 2024 13:11:14 -0500 Subject: [PATCH 09/24] =?UTF-8?q?Make=20`=E2=80=94force`=20to=20skip=20pro?= =?UTF-8?q?mpts=20and=20overwrite.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Console/Commands/StarterKitInit.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Console/Commands/StarterKitInit.php b/src/Console/Commands/StarterKitInit.php index ccadb9ed9e9..4641e0ec3eb 100644 --- a/src/Console/Commands/StarterKitInit.php +++ b/src/Console/Commands/StarterKitInit.php @@ -24,7 +24,8 @@ class StarterKitInit extends Command protected $signature = 'statamic:starter-kit:init { package? : Specify a package for the starter kit (ie. vendor/starter-kit) } { --name : Specify a name for the starter kit } - { --description : Specify a description of the starter kit }'; + { --description : Specify a description of the starter kit } + { --force : Force overwrite if files already exist }'; /** * The console command description. @@ -120,7 +121,7 @@ protected function createConfig(): self $targetPath = base_path('package/starter-kit.yaml'); - if (File::exists($targetPath) && $this->input->isInteractive()) { + if (File::exists($targetPath) && $this->input->isInteractive() && ! $this->option('force')) { if (! confirm('A [starter-kit.yaml] config already exists. Would you like to overwrite it?', false)) { return $this; } @@ -142,7 +143,7 @@ protected function createComposerJson(?string $package, ?string $name, ?string $ $targetPath = base_path('package/composer.json'); - if (File::exists($targetPath) && $this->input->isInteractive()) { + if (File::exists($targetPath) && $this->input->isInteractive() && ! $this->option('force')) { if (! confirm('A [composer.json] config already exists. Would you like to overwrite it?', false)) { return $this; } From 9e33094027c9ed90c3f061334603c920b79d37af Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Wed, 4 Dec 2024 13:28:14 -0500 Subject: [PATCH 10/24] Add prompt to ask if user wants kit `updatable`, and adjust stubbed file. --- src/Console/Commands/StarterKitInit.php | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/Console/Commands/StarterKitInit.php b/src/Console/Commands/StarterKitInit.php index 4641e0ec3eb..28caf4a45ac 100644 --- a/src/Console/Commands/StarterKitInit.php +++ b/src/Console/Commands/StarterKitInit.php @@ -121,13 +121,21 @@ protected function createConfig(): self $targetPath = base_path('package/starter-kit.yaml'); - if (File::exists($targetPath) && $this->input->isInteractive() && ! $this->option('force')) { + if ($this->input->isInteractive() && File::exists($targetPath) && ! $this->option('force')) { if (! confirm('A [starter-kit.yaml] config already exists. Would you like to overwrite it?', false)) { return $this; } } - // TODO: Ask if updatable, and if so prepend `updatable: true` to yaml and create service provider too? + if ($this->input->isInteractive()) { + if (confirm( + label: 'Would you like to make this starter-kit updatable?', + default: false, + hint: 'Read more: https://statamic.dev/starter-kits/creating-a-starter-kit#making-starter-kits-updatable', + )) { + $contents = "updatable: true\n".$contents; + } + } File::put($targetPath, $contents); @@ -143,7 +151,7 @@ protected function createComposerJson(?string $package, ?string $name, ?string $ $targetPath = base_path('package/composer.json'); - if (File::exists($targetPath) && $this->input->isInteractive() && ! $this->option('force')) { + if ($this->input->isInteractive() && File::exists($targetPath) && ! $this->option('force')) { if (! confirm('A [composer.json] config already exists. Would you like to overwrite it?', false)) { return $this; } From 03defc6f6864e91006bd9afbe3bc12295f3fffa7 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Wed, 4 Dec 2024 13:30:37 -0500 Subject: [PATCH 11/24] Todo. --- src/Console/Commands/StarterKitInit.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Console/Commands/StarterKitInit.php b/src/Console/Commands/StarterKitInit.php index 28caf4a45ac..cee48602eaa 100644 --- a/src/Console/Commands/StarterKitInit.php +++ b/src/Console/Commands/StarterKitInit.php @@ -169,6 +169,8 @@ protected function createComposerJson(?string $package, ?string $name, ?string $ $contents = str_replace('A description of your starter kit', $description, $contents); } + // TODO: PSR-4 autoload `src`? Does dir have to exist first? + File::put($targetPath, $contents); return $this; From 3095f76cc83cf100dfb0410edfe6fe8adcb251e6 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Thu, 5 Dec 2024 13:23:08 -0500 Subject: [PATCH 12/24] Extract updatable prompt to method. --- src/Console/Commands/StarterKitInit.php | 32 +++++++++++++++---------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/Console/Commands/StarterKitInit.php b/src/Console/Commands/StarterKitInit.php index cee48602eaa..4b4e9d579bd 100644 --- a/src/Console/Commands/StarterKitInit.php +++ b/src/Console/Commands/StarterKitInit.php @@ -25,6 +25,7 @@ class StarterKitInit extends Command { package? : Specify a package for the starter kit (ie. vendor/starter-kit) } { --name : Specify a name for the starter kit } { --description : Specify a description of the starter kit } + { --updatable : Specify whether the starter kit is to be updatable } { --force : Force overwrite if files already exist }'; /** @@ -42,6 +43,7 @@ public function handle() $package = $this->getKitPackage(); $name = $this->getKitName(); $description = $this->getKitDescription(); + $updatable = $this->getKitUpdatable(); if (! $package || ! $name || ! $description) { $this->components->info('You can manage your starter kit\'s package config in [package/composer.json] at any time.'); @@ -50,8 +52,8 @@ public function handle() $this ->migrateLegacyConfig() ->createFolder() - ->createConfig() - ->createComposerJson($package, $name, $description); + ->createConfig($updatable) + ->createComposerJson($package, $name, $description, $updatable); $this->components->success('Your starter kit config was successfully created in your project\'s [package] folder.'); } @@ -96,6 +98,18 @@ protected function getKitDescription(): ?string return $this->option('description') ?: text('Starter Kit Description'); } + /** + * Get whether the starter kit is to be updatable (optional). + */ + protected function getKitUpdatable(): bool + { + return $this->option('updatable') ?: confirm( + label: 'Would you like to make this starter-kit updatable?', + default: false, + hint: 'Read more: https://statamic.dev/starter-kits/creating-a-starter-kit#making-starter-kits-updatable', + ); + } + /** * Create composer.json config from stub. */ @@ -111,7 +125,7 @@ protected function createFolder(): self /** * Create starter-kit.yaml config from stub. */ - protected function createConfig(): self + protected function createConfig(bool $updatable): self { if ($this->migratedLegacyConfig()) { return $this; @@ -127,14 +141,8 @@ protected function createConfig(): self } } - if ($this->input->isInteractive()) { - if (confirm( - label: 'Would you like to make this starter-kit updatable?', - default: false, - hint: 'Read more: https://statamic.dev/starter-kits/creating-a-starter-kit#making-starter-kits-updatable', - )) { - $contents = "updatable: true\n".$contents; - } + if ($updatable) { + $contents = "updatable: true\n".$contents; } File::put($targetPath, $contents); @@ -145,7 +153,7 @@ protected function createConfig(): self /** * Create composer.json config from stub. */ - protected function createComposerJson(?string $package, ?string $name, ?string $description): self + protected function createComposerJson(?string $package, ?string $name, ?string $description, bool $updatable): self { $contents = File::get(__DIR__.'/stubs/starter-kits/composer.json.stub'); From f2d2448f954d1151cf094e7d1f311dbc25f1bb2d Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Thu, 5 Dec 2024 13:23:25 -0500 Subject: [PATCH 13/24] Dynamically generate composer.json. --- src/Console/Commands/StarterKitInit.php | 55 ++++++++++++++++++++----- 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/src/Console/Commands/StarterKitInit.php b/src/Console/Commands/StarterKitInit.php index 4b4e9d579bd..f1ad3185c3a 100644 --- a/src/Console/Commands/StarterKitInit.php +++ b/src/Console/Commands/StarterKitInit.php @@ -8,6 +8,8 @@ use Statamic\Console\ValidatesInput; use Statamic\Facades\File; use Statamic\Rules\ComposerPackage; +use Statamic\Support\Arr; +use Statamic\Support\Str; use function Laravel\Prompts\confirm; use function Laravel\Prompts\text; @@ -59,7 +61,7 @@ public function handle() } /** - * Get starter kit package for composer.json (optional). + * Get starter kit package (optional). */ protected function getKitPackage(bool $promptingAgain = false): ?string { @@ -83,7 +85,7 @@ protected function getKitPackage(bool $promptingAgain = false): ?string } /** - * Get starter kit name for composer.json (optional). + * Get starter kit name (optional). */ protected function getKitName(): ?string { @@ -91,7 +93,7 @@ protected function getKitName(): ?string } /** - * Get starter kit description for composer.json (optional). + * Get starter kit description (optional). */ protected function getKitDescription(): ?string { @@ -151,12 +153,10 @@ protected function createConfig(bool $updatable): self } /** - * Create composer.json config from stub. + * Create composer.json config. */ protected function createComposerJson(?string $package, ?string $name, ?string $description, bool $updatable): self { - $contents = File::get(__DIR__.'/stubs/starter-kits/composer.json.stub'); - $targetPath = base_path('package/composer.json'); if ($this->input->isInteractive() && File::exists($targetPath) && ! $this->option('force')) { @@ -165,22 +165,55 @@ protected function createComposerJson(?string $package, ?string $name, ?string $ } } + $json = [ + 'name' => 'example/starter-kit-package', + 'extra' => [ + 'statamic' => [ + 'name' => 'Example Name', + 'description' => 'A description of your starter kit', + ], + ], + ]; + if ($package) { - $contents = str_replace('example/starter-kit-package', $package, $contents); + Arr::set($json, 'name', $package); } if ($name) { - $contents = str_replace('Example Name', $name, $contents); + Arr::set($json, 'extra.statamic.name', $name); } if ($description) { - $contents = str_replace('A description of your starter kit', $description, $contents); + Arr::set($json, 'extra.statamic.description', $description); } - // TODO: PSR-4 autoload `src`? Does dir have to exist first? + if ($updatable && $namespace = static::createKitNamespace($package, $name)) { + Arr::set($json, 'autoload.psr-4', [$namespace.'\\' => 'src']); + Arr::set($json, 'autoload-dev.psr-4', ['Tests\\' => 'tests']); + Arr::set($json, 'extra.laravel.providers', [$namespace.'\\ServiceProvider']); + } - File::put($targetPath, $contents); + File::put($targetPath, json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); return $this; } + + /** + * Create kit namespace from name and input if possible. + */ + public static function createKitNamespace(?string $package, ?string $name): string + { + $vendor = 'Example'; + $namespace = 'StarterKitNamespace'; + + if ($package) { + [$vendor, $namespace] = explode('/', $package); + } + + if ($name) { + $namespace = $name; + } + + return Str::upperCamelize($vendor).'\\'.Str::upperCamelize($namespace); + } } From abfc28b9a78de02f1e718853f843684d1c76f4a6 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Thu, 5 Dec 2024 13:23:34 -0500 Subject: [PATCH 14/24] Remove unused stub. --- .../Commands/stubs/starter-kits/composer.json.stub | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 src/Console/Commands/stubs/starter-kits/composer.json.stub diff --git a/src/Console/Commands/stubs/starter-kits/composer.json.stub b/src/Console/Commands/stubs/starter-kits/composer.json.stub deleted file mode 100644 index 627d3f2ea24..00000000000 --- a/src/Console/Commands/stubs/starter-kits/composer.json.stub +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "example/starter-kit-package", - "extra": { - "statamic": { - "name": "Example Name", - "description": "A description of your starter kit" - } - } -} From a586d7efe56a03cff1562b1972bf296b20fdac46 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Thu, 5 Dec 2024 14:48:13 -0500 Subject: [PATCH 15/24] Add guards to fix mockery expectations in non-interactive tests. --- src/Console/Commands/StarterKitInit.php | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/Console/Commands/StarterKitInit.php b/src/Console/Commands/StarterKitInit.php index f1ad3185c3a..c85b24095d5 100644 --- a/src/Console/Commands/StarterKitInit.php +++ b/src/Console/Commands/StarterKitInit.php @@ -25,8 +25,8 @@ class StarterKitInit extends Command */ protected $signature = 'statamic:starter-kit:init { package? : Specify a package for the starter kit (ie. vendor/starter-kit) } - { --name : Specify a name for the starter kit } - { --description : Specify a description of the starter kit } + { --name= : Specify a name for the starter kit } + { --description= : Specify a description of the starter kit } { --updatable : Specify whether the starter kit is to be updatable } { --force : Force overwrite if files already exist }'; @@ -69,8 +69,10 @@ protected function getKitPackage(bool $promptingAgain = false): ?string if ($promptingAgain) { $package = text($promptText); - } else { + } elseif ($this->input->isInteractive()) { $package = $this->argument('package') ?: text($promptText); + } else { + $package = $this->argument('package'); } $fails = $this->validationFails($package, new ComposerPackage); @@ -89,6 +91,10 @@ protected function getKitPackage(bool $promptingAgain = false): ?string */ protected function getKitName(): ?string { + if (! $this->input->isInteractive()) { + return $this->option('name'); + } + return $this->option('name') ?: text('Starter Kit Name (eg. Kung Fury)'); } @@ -97,6 +103,10 @@ protected function getKitName(): ?string */ protected function getKitDescription(): ?string { + if (! $this->input->isInteractive()) { + return $this->option('description'); + } + return $this->option('description') ?: text('Starter Kit Description'); } @@ -105,6 +115,10 @@ protected function getKitDescription(): ?string */ protected function getKitUpdatable(): bool { + if (! $this->input->isInteractive()) { + return $this->option('updatable'); + } + return $this->option('updatable') ?: confirm( label: 'Would you like to make this starter-kit updatable?', default: false, From a4e6c5b3e8c198a9b263bb1025e640ff2a10ec44 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Thu, 5 Dec 2024 14:57:13 -0500 Subject: [PATCH 16/24] Fix issue with package error output. --- src/Console/Commands/StarterKitInit.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Console/Commands/StarterKitInit.php b/src/Console/Commands/StarterKitInit.php index c85b24095d5..30f93cd19c0 100644 --- a/src/Console/Commands/StarterKitInit.php +++ b/src/Console/Commands/StarterKitInit.php @@ -75,12 +75,14 @@ protected function getKitPackage(bool $promptingAgain = false): ?string $package = $this->argument('package'); } - $fails = $this->validationFails($package, new ComposerPackage); + if ($package) { + $fails = $this->validationFails($package, new ComposerPackage); + } if ($package && $fails && $this->input->isInteractive()) { return $this->getKitPackage(true); } elseif ($package && $fails) { - return null; + exit; } return $package; From b955b35068d62645127c45f0f607241fb438dcbd Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Thu, 5 Dec 2024 15:54:43 -0500 Subject: [PATCH 17/24] Add test coverage. --- tests/StarterKits/InitTest.php | 591 +++++++++++++++++++++++++++++++++ 1 file changed, 591 insertions(+) create mode 100644 tests/StarterKits/InitTest.php diff --git a/tests/StarterKits/InitTest.php b/tests/StarterKits/InitTest.php new file mode 100644 index 00000000000..5d7d71fb87d --- /dev/null +++ b/tests/StarterKits/InitTest.php @@ -0,0 +1,591 @@ +files = app(Filesystem::class); + $this->packagePath = base_path('package'); + + $this->cleanUp(); + } + + public function tearDown(): void + { + $this->cleanUp(); + + parent::tearDown(); + } + + private function cleanUp() + { + if ($this->files->exists($this->packagePath)) { + $this->files->deleteDirectory($this->packagePath); + } + } + + #[Test] + public function it_can_init_basic_config() + { + $this->assertFileDoesNotExist($this->packagePath()); + + $this + ->initStarterKit() + ->expectsOutputToContain('You can manage your starter kit\'s package config in [package/composer.json] at any time.') + ->expectsOutputToContain('Your starter kit config was successfully created in your project\'s [package] folder.') + ->assertOk(); + + $this->assertCount(2, $this->files->allFiles($this->packagePath())); + + $this->assertFileExists($configPath = $this->packagePath('starter-kit.yaml')); + $this->assertFileExists($composerJsonPath = $this->packagePath('composer.json')); + + $this->assertEquals(<<<'YAML' +# export_paths: +# - content +# - config/filesystems.php +# - config/statamic/assets.php +# - resources/blueprints +# - resources/css/site.css +# - resources/views +# - public/build +# - package.json +# - tailwind.config.js +# - vite.config.js +YAML, trim($this->files->get($configPath))); + + $this->assertEquals(<<<'JSON' +{ + "name": "example/starter-kit-package", + "extra": { + "statamic": { + "name": "Example Name", + "description": "A description of your starter kit" + } + } +} +JSON, trim($this->files->get($composerJsonPath))); + } + + #[Test] + public function it_can_interactively_init_basic_config() + { + $this->assertFileDoesNotExist($this->packagePath()); + + $this + ->initStarterKitInteractively() + ->expectsQuestion('Starter Kit Package (eg. hasselhoff/kung-fury)', null) + ->expectsQuestion('Starter Kit Name (eg. Kung Fury)', null) + ->expectsQuestion('Starter Kit Description', null) + ->expectsConfirmation('Would you like to make this starter-kit updatable?', 'no') + ->expectsOutputToContain('You can manage your starter kit\'s package config in [package/composer.json] at any time.') + ->expectsOutputToContain('Your starter kit config was successfully created in your project\'s [package] folder.') + ->assertOk(); + + $this->assertCount(2, $this->files->allFiles($this->packagePath())); + + $this->assertFileExists($configPath = $this->packagePath('starter-kit.yaml')); + $this->assertFileExists($composerJsonPath = $this->packagePath('composer.json')); + + $this->assertEquals(<<<'YAML' +# export_paths: +# - content +# - config/filesystems.php +# - config/statamic/assets.php +# - resources/blueprints +# - resources/css/site.css +# - resources/views +# - public/build +# - package.json +# - tailwind.config.js +# - vite.config.js +YAML, trim($this->files->get($configPath))); + + $this->assertEquals(<<<'JSON' +{ + "name": "example/starter-kit-package", + "extra": { + "statamic": { + "name": "Example Name", + "description": "A description of your starter kit" + } + } +} +JSON, trim($this->files->get($composerJsonPath))); + } + + #[Test] + public function it_can_init_with_custom_package_info() + { + $this->assertFileDoesNotExist($this->packagePath()); + + $this + ->initStarterKit([ + 'package' => 'statamic/starter-kit-cool-writings', + '--name' => 'Cool Writings', + '--description' => 'A Cool Runnings inspired starter kit.', + ]) + ->expectsOutputToContain('Your starter kit config was successfully created in your project\'s [package] folder.') + ->assertOk(); + + $this->assertCount(2, $this->files->allFiles($this->packagePath())); + + $this->assertFileExists($configPath = $this->packagePath('starter-kit.yaml')); + $this->assertFileExists($composerJsonPath = $this->packagePath('composer.json')); + + $this->assertEquals(<<<'JSON' +{ + "name": "statamic/starter-kit-cool-writings", + "extra": { + "statamic": { + "name": "Cool Writings", + "description": "A Cool Runnings inspired starter kit." + } + } +} +JSON, trim($this->files->get($composerJsonPath))); + } + + #[Test] + public function it_validates_package() + { + $this->assertFileDoesNotExist($this->packagePath()); + + $this + ->initStarterKit([ + 'package' => 'statamic', + ]) + ->expectsOutputToContain('Must be a valid composer package name (eg. hasselhoff/kung-fury).') + ->doesntExpectOutputToContain('Your starter kit config was successfully created in your project\'s [package] folder.') + ->assertFailed(); + + $this->assertFileDoesNotExist($this->packagePath()); + } + + #[Test] + public function it_can_interactively_init_with_custom_package_info() + { + $this->assertFileDoesNotExist($this->packagePath()); + + $this + ->initStarterKitInteractively() + ->expectsQuestion('Starter Kit Package (eg. hasselhoff/kung-fury)', 'statamic/starter-kit-cool-writings') + ->expectsQuestion('Starter Kit Name (eg. Kung Fury)', 'Cool Writings') + ->expectsQuestion('Starter Kit Description', 'A Cool Runnings inspired starter kit.') + ->expectsConfirmation('Would you like to make this starter-kit updatable?', 'no') + ->expectsOutputToContain('Your starter kit config was successfully created in your project\'s [package] folder.') + ->assertOk(); + + $this->assertCount(2, $this->files->allFiles($this->packagePath())); + + $this->assertFileExists($configPath = $this->packagePath('starter-kit.yaml')); + $this->assertFileExists($composerJsonPath = $this->packagePath('composer.json')); + + $this->assertEquals(<<<'JSON' +{ + "name": "statamic/starter-kit-cool-writings", + "extra": { + "statamic": { + "name": "Cool Writings", + "description": "A Cool Runnings inspired starter kit." + } + } +} +JSON, trim($this->files->get($composerJsonPath))); + } + + #[Test] + public function it_can_init_updatable_kit() + { + $this->assertFileDoesNotExist($this->packagePath()); + + $this + ->initStarterKit(['--updatable' => true]) + ->expectsOutputToContain('Your starter kit config was successfully created in your project\'s [package] folder.') + ->assertOk(); + + $this->assertCount(2, $this->files->allFiles($this->packagePath())); + + $this->assertFileExists($configPath = $this->packagePath('starter-kit.yaml')); + $this->assertFileExists($composerJsonPath = $this->packagePath('composer.json')); + + $this->assertEquals(<<<'YAML' +updatable: true +# export_paths: +# - content +# - config/filesystems.php +# - config/statamic/assets.php +# - resources/blueprints +# - resources/css/site.css +# - resources/views +# - public/build +# - package.json +# - tailwind.config.js +# - vite.config.js +YAML, trim($this->files->get($configPath))); + + $this->assertEquals(<<<'JSON' +{ + "name": "example/starter-kit-package", + "extra": { + "statamic": { + "name": "Example Name", + "description": "A description of your starter kit" + }, + "laravel": { + "providers": [ + "Example\\StarterKitNamespace\\ServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Example\\StarterKitNamespace\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "Tests\\": "tests" + } + } +} +JSON, trim($this->files->get($composerJsonPath))); + } + + #[Test] + public function it_can_interactively_init_updatable_kit() + { + $this->assertFileDoesNotExist($this->packagePath()); + + $this + ->initStarterKitInteractively() + ->expectsQuestion('Starter Kit Package (eg. hasselhoff/kung-fury)', null) + ->expectsQuestion('Starter Kit Name (eg. Kung Fury)', null) + ->expectsQuestion('Starter Kit Description', null) + ->expectsConfirmation('Would you like to make this starter-kit updatable?', 'yes') + ->expectsOutputToContain('Your starter kit config was successfully created in your project\'s [package] folder.') + ->assertOk(); + + $this->assertCount(2, $this->files->allFiles($this->packagePath())); + + $this->assertFileExists($configPath = $this->packagePath('starter-kit.yaml')); + $this->assertFileExists($composerJsonPath = $this->packagePath('composer.json')); + + $this->assertEquals(<<<'YAML' +updatable: true +# export_paths: +# - content +# - config/filesystems.php +# - config/statamic/assets.php +# - resources/blueprints +# - resources/css/site.css +# - resources/views +# - public/build +# - package.json +# - tailwind.config.js +# - vite.config.js +YAML, trim($this->files->get($configPath))); + + $this->assertEquals(<<<'JSON' +{ + "name": "example/starter-kit-package", + "extra": { + "statamic": { + "name": "Example Name", + "description": "A description of your starter kit" + }, + "laravel": { + "providers": [ + "Example\\StarterKitNamespace\\ServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Example\\StarterKitNamespace\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "Tests\\": "tests" + } + } +} +JSON, trim($this->files->get($composerJsonPath))); + } + + #[Test] + public function it_can_init_updatable_kit_with_custom_package_info() + { + $this->assertFileDoesNotExist($this->packagePath()); + + $this + ->initStarterKit([ + 'package' => 'statamic-rad-pack/starter-kit-cool-writings', + '--name' => 'Cool Writings', + '--description' => 'A Cool Runnings inspired starter kit.', + '--updatable' => true, + ]) + ->expectsOutputToContain('Your starter kit config was successfully created in your project\'s [package] folder.') + ->assertOk(); + + $this->assertCount(2, $this->files->allFiles($this->packagePath())); + + $this->assertFileExists($configPath = $this->packagePath('starter-kit.yaml')); + $this->assertFileExists($composerJsonPath = $this->packagePath('composer.json')); + + $this->assertEquals(<<<'JSON' +{ + "name": "statamic-rad-pack/starter-kit-cool-writings", + "extra": { + "statamic": { + "name": "Cool Writings", + "description": "A Cool Runnings inspired starter kit." + }, + "laravel": { + "providers": [ + "StatamicRadPack\\CoolWritings\\ServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "StatamicRadPack\\CoolWritings\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "Tests\\": "tests" + } + } +} +JSON, trim($this->files->get($composerJsonPath))); + } + + #[Test] + public function it_can_interactively_init_updatable_kit_with_custom_package_info() + { + $this->assertFileDoesNotExist($this->packagePath()); + + $this + ->initStarterKitInteractively() + ->expectsQuestion('Starter Kit Package (eg. hasselhoff/kung-fury)', 'statamic-rad-pack/starter-kit-cool-writings') + ->expectsQuestion('Starter Kit Name (eg. Kung Fury)', 'Cool Writings') + ->expectsQuestion('Starter Kit Description', 'A Cool Runnings inspired starter kit.') + ->expectsConfirmation('Would you like to make this starter-kit updatable?', 'yes') + ->expectsOutputToContain('Your starter kit config was successfully created in your project\'s [package] folder.') + ->assertOk(); + + $this->assertCount(2, $this->files->allFiles($this->packagePath())); + + $this->assertFileExists($configPath = $this->packagePath('starter-kit.yaml')); + $this->assertFileExists($composerJsonPath = $this->packagePath('composer.json')); + + $this->assertEquals(<<<'JSON' +{ + "name": "statamic-rad-pack/starter-kit-cool-writings", + "extra": { + "statamic": { + "name": "Cool Writings", + "description": "A Cool Runnings inspired starter kit." + }, + "laravel": { + "providers": [ + "StatamicRadPack\\CoolWritings\\ServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "StatamicRadPack\\CoolWritings\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "Tests\\": "tests" + } + } +} +JSON, trim($this->files->get($composerJsonPath))); + } + + #[Test] + public function it_properly_camel_cases_namespace() + { + $this->assertFileDoesNotExist($this->packagePath()); + + $this + ->initStarterKit([ + '--name' => 'Cool-Writings_Kit ABC', + '--updatable' => true, + ]) + ->expectsOutputToContain('Your starter kit config was successfully created in your project\'s [package] folder.') + ->assertOk(); + + $this->assertCount(2, $this->files->allFiles($this->packagePath())); + + $this->assertFileExists($composerJsonPath = $this->packagePath('composer.json')); + + $this->assertStringContainsString('"Example\\\\CoolWritingsKitABC\\\\": "src"', $this->files->get($composerJsonPath)); + $this->assertStringContainsString('"Example\\\\CoolWritingsKitABC\\\\ServiceProvider"', $this->files->get($composerJsonPath)); + } + + #[Test] + public function it_asks_to_overwrite_existing_files_interactively() + { + $this->files->makeDirectory($this->packagePath()); + $this->files->put($configPath = $this->packagePath('starter-kit.yaml'), $config = 'existing starter-kit.yaml!'); + $this->files->put($composerJsonPath = $this->packagePath('composer.json'), $composerJson = 'existing composer.json!'); + + $this + ->initStarterKitInteractively() + ->expectsQuestion('Starter Kit Package (eg. hasselhoff/kung-fury)', 'statamic/starter-kit-cool-writings') + ->expectsQuestion('Starter Kit Name (eg. Kung Fury)', 'Cool Writings') + ->expectsQuestion('Starter Kit Description', 'A Cool Runnings inspired starter kit.') + ->expectsConfirmation('Would you like to make this starter-kit updatable?', 'no') + ->expectsConfirmation('A [starter-kit.yaml] config already exists. Would you like to overwrite it?', 'no') + ->expectsConfirmation('A [composer.json] config already exists. Would you like to overwrite it?', 'no') + ->expectsOutputToContain('Your starter kit config was successfully created in your project\'s [package] folder.') + ->assertOk(); + + $this->assertCount(2, $this->files->allFiles($this->packagePath())); + + $this->assertFileExists($configPath = $this->packagePath('starter-kit.yaml')); + $this->assertFileExists($composerJsonPath = $this->packagePath('composer.json')); + + $this->assertEquals($config, trim($this->files->get($configPath))); + $this->assertEquals($composerJson, trim($this->files->get($composerJsonPath))); + } + + #[Test] + public function it_can_overwrite_existing_files_interactively() + { + $this->files->makeDirectory($this->packagePath()); + $this->files->put($configPath = $this->packagePath('starter-kit.yaml'), $config = 'existing starter-kit.yaml!'); + $this->files->put($composerJsonPath = $this->packagePath('composer.json'), $composerJson = 'existing composer.json!'); + + $this + ->initStarterKitInteractively() + ->expectsQuestion('Starter Kit Package (eg. hasselhoff/kung-fury)', 'statamic/starter-kit-cool-writings') + ->expectsQuestion('Starter Kit Name (eg. Kung Fury)', 'Cool Writings') + ->expectsQuestion('Starter Kit Description', 'A Cool Runnings inspired starter kit.') + ->expectsConfirmation('Would you like to make this starter-kit updatable?', 'no') + ->expectsConfirmation('A [starter-kit.yaml] config already exists. Would you like to overwrite it?', 'yes') + ->expectsConfirmation('A [composer.json] config already exists. Would you like to overwrite it?', 'yes') + ->expectsOutputToContain('Your starter kit config was successfully created in your project\'s [package] folder.') + ->assertOk(); + + $this->assertCount(2, $this->files->allFiles($this->packagePath())); + + $this->assertFileExists($configPath = $this->packagePath('starter-kit.yaml')); + $this->assertFileExists($composerJsonPath = $this->packagePath('composer.json')); + + $this->assertEquals(<<<'YAML' +# export_paths: +# - content +# - config/filesystems.php +# - config/statamic/assets.php +# - resources/blueprints +# - resources/css/site.css +# - resources/views +# - public/build +# - package.json +# - tailwind.config.js +# - vite.config.js +YAML, trim($this->files->get($configPath))); + + $this->assertEquals(<<<'JSON' +{ + "name": "statamic/starter-kit-cool-writings", + "extra": { + "statamic": { + "name": "Cool Writings", + "description": "A Cool Runnings inspired starter kit." + } + } +} +JSON, trim($this->files->get($composerJsonPath))); + } + + #[Test] + public function it_always_overwrites_existing_files_when_run_non_interactively() + { + $this->files->makeDirectory($this->packagePath()); + $this->files->put($configPath = $this->packagePath('starter-kit.yaml'), $config = 'existing starter-kit.yaml!'); + $this->files->put($composerJsonPath = $this->packagePath('composer.json'), $composerJson = 'existing composer.json!'); + + $this + ->initStarterKit(['package' => 'statamic/starter-kit-cool-writings']) + ->expectsOutputToContain('Your starter kit config was successfully created in your project\'s [package] folder.') + ->assertOk(); + + $this->assertCount(2, $this->files->allFiles($this->packagePath())); + + $this->assertFileExists($configPath = $this->packagePath('starter-kit.yaml')); + $this->assertFileExists($composerJsonPath = $this->packagePath('composer.json')); + + $this->assertEquals(<<<'YAML' +# export_paths: +# - content +# - config/filesystems.php +# - config/statamic/assets.php +# - resources/blueprints +# - resources/css/site.css +# - resources/views +# - public/build +# - package.json +# - tailwind.config.js +# - vite.config.js +YAML, trim($this->files->get($configPath))); + + $this->assertEquals(<<<'JSON' +{ + "name": "statamic/starter-kit-cool-writings", + "extra": { + "statamic": { + "name": "Example Name", + "description": "A description of your starter kit" + } + } +} +JSON, trim($this->files->get($composerJsonPath))); + } + + private function packagePath($path = null) + { + return collect([$this->packagePath, $path])->filter()->implode('/'); + } + + private function initStarterKit($options = []) + { + return $this->artisan('statamic:starter-kit:init', array_merge([ + '--no-interaction' => true, + ], $options)); + } + + private function initStarterKitInteractively($options = []) + { + return $this->artisan('statamic:starter-kit:init', $options); + } + + private function assertFileHasContent($expected, $path) + { + $this->assertFileExists($path); + + $this->assertStringContainsString($expected, $this->files->get($path)); + } +} From 7e204fbe8aef569d8685843685ab5d23c1f2db16 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Thu, 5 Dec 2024 15:55:07 -0500 Subject: [PATCH 18/24] Pass tests around `package` validation error. --- src/Console/Commands/StarterKitInit.php | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/Console/Commands/StarterKitInit.php b/src/Console/Commands/StarterKitInit.php index 30f93cd19c0..41b7bf769f5 100644 --- a/src/Console/Commands/StarterKitInit.php +++ b/src/Console/Commands/StarterKitInit.php @@ -8,6 +8,7 @@ use Statamic\Console\ValidatesInput; use Statamic\Facades\File; use Statamic\Rules\ComposerPackage; +use Statamic\StarterKits\Exceptions\StarterKitException; use Statamic\Support\Arr; use Statamic\Support\Str; @@ -42,10 +43,14 @@ class StarterKitInit extends Command */ public function handle() { - $package = $this->getKitPackage(); - $name = $this->getKitName(); - $description = $this->getKitDescription(); - $updatable = $this->getKitUpdatable(); + try { + $package = $this->getKitPackage(); + $name = $this->getKitName(); + $description = $this->getKitDescription(); + $updatable = $this->getKitUpdatable(); + } catch (StarterKitException $exception) { + return 1; + } if (! $package || ! $name || ! $description) { $this->components->info('You can manage your starter kit\'s package config in [package/composer.json] at any time.'); @@ -82,7 +87,7 @@ protected function getKitPackage(bool $promptingAgain = false): ?string if ($package && $fails && $this->input->isInteractive()) { return $this->getKitPackage(true); } elseif ($package && $fails) { - exit; + throw new StarterKitException; } return $package; From 9e4b24b4ee6484704caae20a8eaa1b3e6171e790 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Thu, 5 Dec 2024 16:13:46 -0500 Subject: [PATCH 19/24] Refactor to use properties. --- src/Console/Commands/StarterKitInit.php | 78 +++++++++++++++++-------- 1 file changed, 54 insertions(+), 24 deletions(-) diff --git a/src/Console/Commands/StarterKitInit.php b/src/Console/Commands/StarterKitInit.php index 41b7bf769f5..bcd2411bf57 100644 --- a/src/Console/Commands/StarterKitInit.php +++ b/src/Console/Commands/StarterKitInit.php @@ -38,29 +38,57 @@ class StarterKitInit extends Command */ protected $description = 'Create a new starter kit config'; + /** + * The installable package. + * + * @var ?string + */ + protected $package; + + /** + * The name of the starter kit. + * + * @var ?string + */ + protected $kitName; + + /** + * The description of the starter kit. + * + * @var ?string + */ + protected $kitDescription; + + /** + * Whether or not the kit should be updatable. + * + * @var bool + */ + protected $updatable = false; + /** * Execute the console command. */ public function handle() { try { - $package = $this->getKitPackage(); - $name = $this->getKitName(); - $description = $this->getKitDescription(); - $updatable = $this->getKitUpdatable(); + $this->package = $this->getKitPackage(); + $this->kitName = $this->getKitName(); + $this->kitDescription = $this->getKitDescription(); + $this->updatable = $this->getKitUpdatable(); } catch (StarterKitException $exception) { return 1; } - if (! $package || ! $name || ! $description) { + if (! $this->package || ! $this->kitName || ! $this->kitDescription) { $this->components->info('You can manage your starter kit\'s package config in [package/composer.json] at any time.'); } $this ->migrateLegacyConfig() ->createFolder() - ->createConfig($updatable) - ->createComposerJson($package, $name, $description, $updatable); + ->createConfig() + ->createComposerJson(); $this->components->success('Your starter kit config was successfully created in your project\'s [package] folder.'); } @@ -136,9 +164,11 @@ protected function getKitUpdatable(): bool /** * Create composer.json config from stub. */ - protected function createFolder(): self + protected function createFolder($dir = null): self { - if (! File::exists($dir = base_path('package'))) { + $dir ??= base_path('package'); + + if (! File::exists($dir)) { File::makeDirectory($dir, 0755, true); } @@ -148,7 +178,7 @@ protected function createFolder(): self /** * Create starter-kit.yaml config from stub. */ - protected function createConfig(bool $updatable): self + protected function createConfig(): self { if ($this->migratedLegacyConfig()) { return $this; @@ -164,7 +194,7 @@ protected function createConfig(bool $updatable): self } } - if ($updatable) { + if ($this->updatable) { $contents = "updatable: true\n".$contents; } @@ -176,7 +206,7 @@ protected function createConfig(bool $updatable): self /** * Create composer.json config. */ - protected function createComposerJson(?string $package, ?string $name, ?string $description, bool $updatable): self + protected function createComposerJson(): self { $targetPath = base_path('package/composer.json'); @@ -196,19 +226,19 @@ protected function createComposerJson(?string $package, ?string $name, ?string $ ], ]; - if ($package) { - Arr::set($json, 'name', $package); + if ($this->package) { + Arr::set($json, 'name', $this->package); } - if ($name) { - Arr::set($json, 'extra.statamic.name', $name); + if ($this->kitName) { + Arr::set($json, 'extra.statamic.name', $this->kitName); } - if ($description) { - Arr::set($json, 'extra.statamic.description', $description); + if ($this->kitDescription) { + Arr::set($json, 'extra.statamic.description', $this->kitDescription); } - if ($updatable && $namespace = static::createKitNamespace($package, $name)) { + if ($this->updatable && $namespace = $this->kitNamespace()) { Arr::set($json, 'autoload.psr-4', [$namespace.'\\' => 'src']); Arr::set($json, 'autoload-dev.psr-4', ['Tests\\' => 'tests']); Arr::set($json, 'extra.laravel.providers', [$namespace.'\\ServiceProvider']); @@ -222,17 +252,17 @@ protected function createComposerJson(?string $package, ?string $name, ?string $ /** * Create kit namespace from name and input if possible. */ - public static function createKitNamespace(?string $package, ?string $name): string + public function kitNamespace(): string { $vendor = 'Example'; $namespace = 'StarterKitNamespace'; - if ($package) { - [$vendor, $namespace] = explode('/', $package); + if ($this->package) { + [$vendor, $namespace] = explode('/', $this->package); } - if ($name) { - $namespace = $name; + if ($this->kitName) { + $namespace = $this->kitName; } return Str::upperCamelize($vendor).'\\'.Str::upperCamelize($namespace); From 196e2e21504bd297d316a012ff4864891a72d0a6 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Thu, 5 Dec 2024 16:20:55 -0500 Subject: [PATCH 20/24] Add service provider stub. --- .../stubs/starter-kits/ServiceProvider.php.stub | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/Console/Commands/stubs/starter-kits/ServiceProvider.php.stub diff --git a/src/Console/Commands/stubs/starter-kits/ServiceProvider.php.stub b/src/Console/Commands/stubs/starter-kits/ServiceProvider.php.stub new file mode 100644 index 00000000000..6a98bebb9d6 --- /dev/null +++ b/src/Console/Commands/stubs/starter-kits/ServiceProvider.php.stub @@ -0,0 +1,13 @@ + Date: Thu, 5 Dec 2024 16:21:19 -0500 Subject: [PATCH 21/24] Create service provider in updatable kits. --- src/Console/Commands/StarterKitInit.php | 31 ++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/Console/Commands/StarterKitInit.php b/src/Console/Commands/StarterKitInit.php index bcd2411bf57..6ba36222958 100644 --- a/src/Console/Commands/StarterKitInit.php +++ b/src/Console/Commands/StarterKitInit.php @@ -88,7 +88,8 @@ public function handle() ->migrateLegacyConfig() ->createFolder() ->createConfig() - ->createComposerJson(); + ->createComposerJson() + ->createServiceProvider(); $this->components->success('Your starter kit config was successfully created in your project\'s [package] folder.'); } @@ -249,6 +250,34 @@ protected function createComposerJson(): self return $this; } + /** + * Create service provider. + */ + protected function createServiceProvider(): self + { + if (! $this->updatable) { + return $this; + } + + $this->createFolder(base_path('package/src')); + + $contents = File::get(__DIR__.'/stubs/starter-kits/ServiceProvider.php.stub'); + + $targetPath = base_path('package/src/ServiceProvider.php'); + + if ($this->input->isInteractive() && File::exists($targetPath) && ! $this->option('force')) { + if (! confirm('A service provider already exists at [src/ServiceProvider.php]. Would you like to overwrite it?', false)) { + return $this; + } + } + + $contents = str_replace('DummyNamespace', $this->kitNamespace(), $contents); + + File::put($targetPath, $contents); + + return $this; + } + /** * Create kit namespace from name and input if possible. */ From 0411923a444f9430bb576ffeb2c8e384b510a937 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Thu, 5 Dec 2024 16:21:24 -0500 Subject: [PATCH 22/24] Test coverage. --- tests/StarterKits/InitTest.php | 80 +++++++++++++++++++++++++++++++--- 1 file changed, 75 insertions(+), 5 deletions(-) diff --git a/tests/StarterKits/InitTest.php b/tests/StarterKits/InitTest.php index 5d7d71fb87d..4880793f4ff 100644 --- a/tests/StarterKits/InitTest.php +++ b/tests/StarterKits/InitTest.php @@ -218,10 +218,11 @@ public function it_can_init_updatable_kit() ->expectsOutputToContain('Your starter kit config was successfully created in your project\'s [package] folder.') ->assertOk(); - $this->assertCount(2, $this->files->allFiles($this->packagePath())); + $this->assertCount(3, $this->files->allFiles($this->packagePath())); $this->assertFileExists($configPath = $this->packagePath('starter-kit.yaml')); $this->assertFileExists($composerJsonPath = $this->packagePath('composer.json')); + $this->assertFileExists($serviceProviderPath = $this->packagePath('src/ServiceProvider.php')); $this->assertEquals(<<<'YAML' updatable: true @@ -264,6 +265,22 @@ public function it_can_init_updatable_kit() } } JSON, trim($this->files->get($composerJsonPath))); + + $this->assertEquals(<<<'PHP' +files->get($serviceProviderPath))); } #[Test] @@ -280,10 +297,11 @@ public function it_can_interactively_init_updatable_kit() ->expectsOutputToContain('Your starter kit config was successfully created in your project\'s [package] folder.') ->assertOk(); - $this->assertCount(2, $this->files->allFiles($this->packagePath())); + $this->assertCount(3, $this->files->allFiles($this->packagePath())); $this->assertFileExists($configPath = $this->packagePath('starter-kit.yaml')); $this->assertFileExists($composerJsonPath = $this->packagePath('composer.json')); + $this->assertFileExists($serviceProviderPath = $this->packagePath('src/ServiceProvider.php')); $this->assertEquals(<<<'YAML' updatable: true @@ -326,6 +344,22 @@ public function it_can_interactively_init_updatable_kit() } } JSON, trim($this->files->get($composerJsonPath))); + + $this->assertEquals(<<<'PHP' +files->get($serviceProviderPath))); } #[Test] @@ -343,10 +377,11 @@ public function it_can_init_updatable_kit_with_custom_package_info() ->expectsOutputToContain('Your starter kit config was successfully created in your project\'s [package] folder.') ->assertOk(); - $this->assertCount(2, $this->files->allFiles($this->packagePath())); + $this->assertCount(3, $this->files->allFiles($this->packagePath())); $this->assertFileExists($configPath = $this->packagePath('starter-kit.yaml')); $this->assertFileExists($composerJsonPath = $this->packagePath('composer.json')); + $this->assertFileExists($serviceProviderPath = $this->packagePath('src/ServiceProvider.php')); $this->assertEquals(<<<'JSON' { @@ -374,6 +409,22 @@ public function it_can_init_updatable_kit_with_custom_package_info() } } JSON, trim($this->files->get($composerJsonPath))); + + $this->assertEquals(<<<'PHP' +files->get($serviceProviderPath))); } #[Test] @@ -390,10 +441,11 @@ public function it_can_interactively_init_updatable_kit_with_custom_package_info ->expectsOutputToContain('Your starter kit config was successfully created in your project\'s [package] folder.') ->assertOk(); - $this->assertCount(2, $this->files->allFiles($this->packagePath())); + $this->assertCount(3, $this->files->allFiles($this->packagePath())); $this->assertFileExists($configPath = $this->packagePath('starter-kit.yaml')); $this->assertFileExists($composerJsonPath = $this->packagePath('composer.json')); + $this->assertFileExists($serviceProviderPath = $this->packagePath('src/ServiceProvider.php')); $this->assertEquals(<<<'JSON' { @@ -421,6 +473,22 @@ public function it_can_interactively_init_updatable_kit_with_custom_package_info } } JSON, trim($this->files->get($composerJsonPath))); + + $this->assertEquals(<<<'PHP' +files->get($serviceProviderPath))); } #[Test] @@ -436,12 +504,14 @@ public function it_properly_camel_cases_namespace() ->expectsOutputToContain('Your starter kit config was successfully created in your project\'s [package] folder.') ->assertOk(); - $this->assertCount(2, $this->files->allFiles($this->packagePath())); + $this->assertCount(3, $this->files->allFiles($this->packagePath())); $this->assertFileExists($composerJsonPath = $this->packagePath('composer.json')); + $this->assertFileExists($serviceProviderPath = $this->packagePath('src/ServiceProvider.php')); $this->assertStringContainsString('"Example\\\\CoolWritingsKitABC\\\\": "src"', $this->files->get($composerJsonPath)); $this->assertStringContainsString('"Example\\\\CoolWritingsKitABC\\\\ServiceProvider"', $this->files->get($composerJsonPath)); + $this->assertStringContainsString('namespace Example\\CoolWritingsKitABC;', $this->files->get($serviceProviderPath)); } #[Test] From fe05bffc81533f8d2f10ac2a75a395312a789924 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Thu, 5 Dec 2024 16:45:09 -0500 Subject: [PATCH 23/24] =?UTF-8?q?This=20is=20why=20we=20can=E2=80=99t=20ha?= =?UTF-8?q?ve=20nice=20things.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Console/Commands/StarterKitExport.php | 4 ++++ src/Console/Commands/StarterKitInit.php | 4 ++++ src/Console/Commands/StarterKitInstall.php | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/src/Console/Commands/StarterKitExport.php b/src/Console/Commands/StarterKitExport.php index e93969ddcd0..74df3e99a13 100644 --- a/src/Console/Commands/StarterKitExport.php +++ b/src/Console/Commands/StarterKitExport.php @@ -56,6 +56,10 @@ public function handle() return 1; } + if (version_compare(app()->version(), '11', '<')) { + return $this->components->info("Starter kit was successfully exported to [$path]."); + } + $this->components->success("Starter kit was successfully exported to [$path]."); } diff --git a/src/Console/Commands/StarterKitInit.php b/src/Console/Commands/StarterKitInit.php index 6ba36222958..e26f02d7293 100644 --- a/src/Console/Commands/StarterKitInit.php +++ b/src/Console/Commands/StarterKitInit.php @@ -91,6 +91,10 @@ public function handle() ->createComposerJson() ->createServiceProvider(); + if (version_compare(app()->version(), '11', '<')) { + return $this->components->info('Your starter kit config was successfully created in your project\'s [package] folder.'); + } + $this->components->success('Your starter kit config was successfully created in your project\'s [package] folder.'); } diff --git a/src/Console/Commands/StarterKitInstall.php b/src/Console/Commands/StarterKitInstall.php index bf8142f8f74..3dc63df0887 100644 --- a/src/Console/Commands/StarterKitInstall.php +++ b/src/Console/Commands/StarterKitInstall.php @@ -90,6 +90,10 @@ public function handle() $this->comment('composer global update statamic/cli'.PHP_EOL); } + if (version_compare(app()->version(), '11', '<')) { + return $this->components->info("Starter kit [$package] was successfully installed."); + } + $this->components->success("Starter kit [$package] was successfully installed."); } From c10b1392811a4acadcc709d4259e6da538f5c503 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Thu, 5 Dec 2024 17:00:47 -0500 Subject: [PATCH 24/24] Ignore line endings. --- tests/StarterKits/InitTest.php | 40 +++++++++++++++++----------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/tests/StarterKits/InitTest.php b/tests/StarterKits/InitTest.php index 4880793f4ff..2211f6ca5c4 100644 --- a/tests/StarterKits/InitTest.php +++ b/tests/StarterKits/InitTest.php @@ -54,7 +54,7 @@ public function it_can_init_basic_config() $this->assertFileExists($configPath = $this->packagePath('starter-kit.yaml')); $this->assertFileExists($composerJsonPath = $this->packagePath('composer.json')); - $this->assertEquals(<<<'YAML' + $this->assertStringEqualsStringIgnoringLineEndings(<<<'YAML' # export_paths: # - content # - config/filesystems.php @@ -68,7 +68,7 @@ public function it_can_init_basic_config() # - vite.config.js YAML, trim($this->files->get($configPath))); - $this->assertEquals(<<<'JSON' + $this->assertStringEqualsStringIgnoringLineEndings(<<<'JSON' { "name": "example/starter-kit-package", "extra": { @@ -101,7 +101,7 @@ public function it_can_interactively_init_basic_config() $this->assertFileExists($configPath = $this->packagePath('starter-kit.yaml')); $this->assertFileExists($composerJsonPath = $this->packagePath('composer.json')); - $this->assertEquals(<<<'YAML' + $this->assertStringEqualsStringIgnoringLineEndings(<<<'YAML' # export_paths: # - content # - config/filesystems.php @@ -115,7 +115,7 @@ public function it_can_interactively_init_basic_config() # - vite.config.js YAML, trim($this->files->get($configPath))); - $this->assertEquals(<<<'JSON' + $this->assertStringEqualsStringIgnoringLineEndings(<<<'JSON' { "name": "example/starter-kit-package", "extra": { @@ -147,7 +147,7 @@ public function it_can_init_with_custom_package_info() $this->assertFileExists($configPath = $this->packagePath('starter-kit.yaml')); $this->assertFileExists($composerJsonPath = $this->packagePath('composer.json')); - $this->assertEquals(<<<'JSON' + $this->assertStringEqualsStringIgnoringLineEndings(<<<'JSON' { "name": "statamic/starter-kit-cool-writings", "extra": { @@ -195,7 +195,7 @@ public function it_can_interactively_init_with_custom_package_info() $this->assertFileExists($configPath = $this->packagePath('starter-kit.yaml')); $this->assertFileExists($composerJsonPath = $this->packagePath('composer.json')); - $this->assertEquals(<<<'JSON' + $this->assertStringEqualsStringIgnoringLineEndings(<<<'JSON' { "name": "statamic/starter-kit-cool-writings", "extra": { @@ -224,7 +224,7 @@ public function it_can_init_updatable_kit() $this->assertFileExists($composerJsonPath = $this->packagePath('composer.json')); $this->assertFileExists($serviceProviderPath = $this->packagePath('src/ServiceProvider.php')); - $this->assertEquals(<<<'YAML' + $this->assertStringEqualsStringIgnoringLineEndings(<<<'YAML' updatable: true # export_paths: # - content @@ -239,7 +239,7 @@ public function it_can_init_updatable_kit() # - vite.config.js YAML, trim($this->files->get($configPath))); - $this->assertEquals(<<<'JSON' + $this->assertStringEqualsStringIgnoringLineEndings(<<<'JSON' { "name": "example/starter-kit-package", "extra": { @@ -266,7 +266,7 @@ public function it_can_init_updatable_kit() } JSON, trim($this->files->get($composerJsonPath))); - $this->assertEquals(<<<'PHP' + $this->assertStringEqualsStringIgnoringLineEndings(<<<'PHP' assertFileExists($composerJsonPath = $this->packagePath('composer.json')); $this->assertFileExists($serviceProviderPath = $this->packagePath('src/ServiceProvider.php')); - $this->assertEquals(<<<'YAML' + $this->assertStringEqualsStringIgnoringLineEndings(<<<'YAML' updatable: true # export_paths: # - content @@ -318,7 +318,7 @@ public function it_can_interactively_init_updatable_kit() # - vite.config.js YAML, trim($this->files->get($configPath))); - $this->assertEquals(<<<'JSON' + $this->assertStringEqualsStringIgnoringLineEndings(<<<'JSON' { "name": "example/starter-kit-package", "extra": { @@ -345,7 +345,7 @@ public function it_can_interactively_init_updatable_kit() } JSON, trim($this->files->get($composerJsonPath))); - $this->assertEquals(<<<'PHP' + $this->assertStringEqualsStringIgnoringLineEndings(<<<'PHP' assertFileExists($composerJsonPath = $this->packagePath('composer.json')); $this->assertFileExists($serviceProviderPath = $this->packagePath('src/ServiceProvider.php')); - $this->assertEquals(<<<'JSON' + $this->assertStringEqualsStringIgnoringLineEndings(<<<'JSON' { "name": "statamic-rad-pack/starter-kit-cool-writings", "extra": { @@ -410,7 +410,7 @@ public function it_can_init_updatable_kit_with_custom_package_info() } JSON, trim($this->files->get($composerJsonPath))); - $this->assertEquals(<<<'PHP' + $this->assertStringEqualsStringIgnoringLineEndings(<<<'PHP' assertFileExists($composerJsonPath = $this->packagePath('composer.json')); $this->assertFileExists($serviceProviderPath = $this->packagePath('src/ServiceProvider.php')); - $this->assertEquals(<<<'JSON' + $this->assertStringEqualsStringIgnoringLineEndings(<<<'JSON' { "name": "statamic-rad-pack/starter-kit-cool-writings", "extra": { @@ -474,7 +474,7 @@ public function it_can_interactively_init_updatable_kit_with_custom_package_info } JSON, trim($this->files->get($composerJsonPath))); - $this->assertEquals(<<<'PHP' + $this->assertStringEqualsStringIgnoringLineEndings(<<<'PHP' assertFileExists($configPath = $this->packagePath('starter-kit.yaml')); $this->assertFileExists($composerJsonPath = $this->packagePath('composer.json')); - $this->assertEquals(<<<'YAML' + $this->assertStringEqualsStringIgnoringLineEndings(<<<'YAML' # export_paths: # - content # - config/filesystems.php @@ -578,7 +578,7 @@ public function it_can_overwrite_existing_files_interactively() # - vite.config.js YAML, trim($this->files->get($configPath))); - $this->assertEquals(<<<'JSON' + $this->assertStringEqualsStringIgnoringLineEndings(<<<'JSON' { "name": "statamic/starter-kit-cool-writings", "extra": { @@ -608,7 +608,7 @@ public function it_always_overwrites_existing_files_when_run_non_interactively() $this->assertFileExists($configPath = $this->packagePath('starter-kit.yaml')); $this->assertFileExists($composerJsonPath = $this->packagePath('composer.json')); - $this->assertEquals(<<<'YAML' + $this->assertStringEqualsStringIgnoringLineEndings(<<<'YAML' # export_paths: # - content # - config/filesystems.php @@ -622,7 +622,7 @@ public function it_always_overwrites_existing_files_when_run_non_interactively() # - vite.config.js YAML, trim($this->files->get($configPath))); - $this->assertEquals(<<<'JSON' + $this->assertStringEqualsStringIgnoringLineEndings(<<<'JSON' { "name": "statamic/starter-kit-cool-writings", "extra": {