1111use BlameButton \LaravelDockerBuilder \Detector \NodePackageManagerDetector ;
1212use BlameButton \LaravelDockerBuilder \Detector \PhpExtensionsDetector ;
1313use BlameButton \LaravelDockerBuilder \Detector \PhpVersionDetector ;
14+ use BlameButton \LaravelDockerBuilder \Exceptions \InvalidOptionValueException ;
1415use BlameButton \LaravelDockerBuilder \Traits \InteractsWithTwig ;
15- use Illuminate \Support \Collection ;
1616use Symfony \Component \Console \Input \InputOption ;
1717
1818class DockerGenerateCommand extends BaseCommand
@@ -25,63 +25,77 @@ class DockerGenerateCommand extends BaseCommand
2525
2626 public function handle (): int
2727 {
28- $ phpVersion = $ this ->getPhpVersion ();
29- $ phpExtensions = $ this ->getPhpExtensions ($ phpVersion );
30- $ artisanOptimize = $ this ->getArtisanOptimize ();
31- $ nodePackageManager = $ this ->getNodePackageManager ();
32- $ nodeBuildTool = $ nodePackageManager ? $ this ->getNodeBuildTool () : false ;
33-
34- if ($ this ->option ('detect ' )) {
35- $ this ->info ('Detected Configuration ' );
28+ try {
29+ $ phpVersion = $ this ->getPhpVersion ();
30+ $ phpExtensions = $ this ->getPhpExtensions ($ phpVersion );
31+ $ artisanOptimize = $ this ->getArtisanOptimize ();
32+ $ nodePackageManager = $ this ->getNodePackageManager ();
33+ $ nodeBuildTool = $ nodePackageManager ? $ this ->getNodeBuildTool () : false ;
34+ } catch (InvalidOptionValueException $ exception ) {
35+ $ this ->error ($ exception ->getMessage ());
36+
37+ return self ::INVALID ;
3638 }
3739
40+ $ this ->info ('Configuration: ' );
3841 $ this ->table (['Key ' , 'Value ' ], [
3942 ['PHP version ' , "<comment> $ phpVersion</comment> " ],
4043 ['PHP extensions ' , implode (', ' , $ phpExtensions )],
4144 ['Artisan Optimize ' , '<comment> ' .json_encode ($ artisanOptimize ).'</comment> ' ],
4245 ['Node Package Manager ' , NodePackageManager::name ($ nodePackageManager )],
4346 ['Node Build Tool ' , $ nodePackageManager ? NodeBuildTool::name ($ nodeBuildTool ) : 'None ' ],
4447 ]);
48+ $ this ->newLine ();
4549
46- $ dockerfiles = collect ([
47- 'php.dockerfile ' => $ this ->render ('php.dockerfile.twig ' , [
48- 'php_version ' => $ phpVersion ,
49- 'php_extensions ' => $ phpExtensions ,
50- 'artisan_optimize ' => $ artisanOptimize ,
51- 'node_package_manager ' => $ nodePackageManager ,
52- 'node_build_tool ' => $ nodeBuildTool ,
53- ]),
54- 'nginx.dockerfile ' => $ this ->render ('nginx.dockerfile.twig ' , [
55- 'node_package_manager ' => $ nodePackageManager ,
56- 'node_build_tool ' => $ nodeBuildTool ,
57- ]),
58- ]);
50+ if (! $ this ->option ('no-interaction ' ) && ! $ this ->confirm ('Does this look correct? ' , true )) {
51+ $ this ->comment ('Exiting. ' );
5952
60- if (! is_dir ($ dir = base_path ('.docker ' ))) {
61- mkdir ($ dir );
53+ return self ::SUCCESS ;
6254 }
6355
64- foreach ($ dockerfiles as $ file => $ content ) {
65- // Example: $PWD/.docker/{php,nginx}.dockerfile
66- $ dockerfile = sprintf ('%s/%s ' , $ dir , $ file );
56+ $ context = [
57+ 'php_version ' => $ phpVersion ,
58+ 'php_extensions ' => $ phpExtensions ,
59+ 'artisan_optimize ' => $ artisanOptimize ,
60+ 'node_package_manager ' => $ nodePackageManager ,
61+ 'node_build_tool ' => $ nodeBuildTool ,
62+ ];
6763
68- // Save Dockerfile contents
69- file_put_contents ($ dockerfile , $ content );
64+ $ this ->saveDockerfiles ($ context );
65+ $ this ->newLine ();
66+
67+ $ command = array_filter ([
68+ 'php ' ,
69+ 'artisan ' ,
70+ 'docker:generate ' ,
71+ '-n ' , // --no-interaction
72+ '-p ' .$ phpVersion , // --php-version
73+ '-e ' .implode (', ' , $ phpExtensions ), // --php-extensions
74+ $ artisanOptimize ? '-o ' : null , // --optimize
75+ $ nodePackageManager ? '-m ' .$ nodePackageManager : null , // --node-package-manager
76+ $ nodePackageManager ? '-b ' .$ nodeBuildTool : null , // --node-build-tool
77+ ]);
7078
71- // Output saved Dockerfile location
72- $ filename = str ($ dockerfile )->after (base_path ())->trim ('/ ' );
73- $ this ->info (sprintf ('Saved: %s ' , $ filename ));
74- }
79+ $ this ->info ('Command to generate above configuration: ' );
80+ $ this ->comment (sprintf (' %s ' , implode (' ' , $ command )));
7581
7682 return self ::SUCCESS ;
7783 }
7884
85+ /**
86+ * Get the PHP version, either by detecting it from the "composer.json",
87+ * from the "php-version" option, or asking the user.
88+ *
89+ * @return string
90+ *
91+ * @throws InvalidOptionValueException when an unsupported PHP version is passed
92+ */
7993 private function getPhpVersion (): string
8094 {
8195 if ($ option = $ this ->option ('php-version ' )) {
8296 return in_array ($ option , PhpVersion::values ())
8397 ? $ option
84- : throw new \ InvalidArgumentException ("Invalid value [ $ option] for option [php-version] " );
98+ : throw new InvalidOptionValueException ("Invalid value [ $ option] for option [php-version] " );
8599 }
86100
87101 $ detected = app (PhpVersionDetector::class)->detect ();
@@ -97,14 +111,31 @@ private function getPhpVersion(): string
97111 );
98112 }
99113
114+ /**
115+ * Get the PHP extensions, either by detecting them from the application's configuration,
116+ * from the "php-extensions" option, or asking the user.
117+ *
118+ * @param string $phpVersion
119+ * @return array
120+ *
121+ * @throws InvalidOptionValueException when an unsupported extension is passed
122+ */
100123 private function getPhpExtensions (string $ phpVersion ): array
101124 {
102125 $ supportedExtensions = PhpExtensions::values ($ phpVersion );
103126
104127 if ($ option = $ this ->option ('php-extensions ' )) {
105- return Collection::make (explode (', ' , $ option ))
106- ->intersect ($ supportedExtensions )
107- ->toArray ();
128+ $ extensions = explode (', ' , $ option );
129+
130+ foreach ($ extensions as $ extension ) {
131+ if (in_array ($ extension , $ supportedExtensions )) {
132+ continue ;
133+ }
134+
135+ throw new InvalidOptionValueException ("Extension [ $ extension] is not supported. " );
136+ }
137+
138+ return array_intersect ($ extensions , $ supportedExtensions );
108139 }
109140
110141 $ detected = app (PhpExtensionsDetector::class, ['supportedExtensions ' => $ supportedExtensions ])->detect ();
@@ -142,12 +173,20 @@ public function getArtisanOptimize(): bool
142173 return ArtisanOptimize::YES === $ choice ;
143174 }
144175
176+ /**
177+ * Get the Node Package Manager, either by detecting it from files present (package-lock.json, yarn.lock),
178+ * from the "node-package-manager" option, or asking the user.
179+ *
180+ * @return string|false
181+ *
182+ * @throws InvalidOptionValueException
183+ */
145184 private function getNodePackageManager (): string |false
146185 {
147186 if ($ option = $ this ->option ('node-package-manager ' )) {
148187 return in_array ($ option , NodePackageManager::values ())
149188 ? $ option
150- : throw new \ InvalidArgumentException ("Invalid value [ $ option] for option [node-package-manager] " );
189+ : throw new InvalidOptionValueException ("Invalid value [ $ option] for option [node-package-manager] " );
151190 }
152191
153192 $ detected = app (NodePackageManagerDetector::class)->detect ();
@@ -163,12 +202,20 @@ private function getNodePackageManager(): string|false
163202 );
164203 }
165204
205+ /**
206+ * Get the Node Build Tool, either by detecting it from files present (vite.config.js, webpack.mix.js),
207+ * from the "node-build-tool" option, or asking the user.
208+ *
209+ * @return string
210+ *
211+ * @throws InvalidOptionValueException
212+ */
166213 private function getNodeBuildTool (): string
167214 {
168215 if ($ option = $ this ->option ('node-build-tool ' )) {
169216 return in_array ($ option , NodeBuildTool::values ())
170217 ? $ option
171- : throw new \ InvalidArgumentException ("Invalid value [ $ option] for option [node-build-tool] " );
218+ : throw new InvalidOptionValueException ("Invalid value [ $ option] for option [node-build-tool] " );
172219 }
173220
174221 $ detected = app (NodeBuildToolDetector::class)->detect ();
@@ -184,6 +231,32 @@ private function getNodeBuildTool(): string
184231 );
185232 }
186233
234+ private function saveDockerfiles (array $ context ): void
235+ {
236+ if (! is_dir ($ dir = base_path ('.docker ' ))) {
237+ mkdir ($ dir );
238+ }
239+
240+ $ this ->info ('Saving Dockerfiles: ' );
241+
242+ $ dockerfiles = [
243+ 'php.dockerfile ' => $ this ->render ('php.dockerfile.twig ' , $ context ),
244+ 'nginx.dockerfile ' => $ this ->render ('nginx.dockerfile.twig ' , $ context ),
245+ ];
246+
247+ foreach ($ dockerfiles as $ file => $ content ) {
248+ // Example: $PWD/.docker/{php,nginx}.dockerfile
249+ $ dockerfile = sprintf ('%s/%s ' , $ dir , $ file );
250+
251+ // Save Dockerfile contents
252+ file_put_contents ($ dockerfile , $ content );
253+
254+ // Output saved Dockerfile location
255+ $ filename = str ($ dockerfile )->after (base_path ())->trim ('/ ' );
256+ $ this ->comment (sprintf (' Saved: %s ' , $ filename ));
257+ }
258+ }
259+
187260 protected function getOptions (): array
188261 {
189262 return [
0 commit comments