1515use Symfony \Component \Console \Input \InputInterface ;
1616use Symfony \Component \Console \Input \InputOption ;
1717use Symfony \Component \Console \Output \OutputInterface ;
18+ use Magento \Framework \Filesystem \Driver \File ;
1819
1920use function Laravel \Prompts \confirm ;
2021use function Laravel \Prompts \search ;
2122
2223class CopyFromVendorCommand extends AbstractCommand
2324{
25+ /**
26+ * @param ThemeList $themeList
27+ * @param VendorFileMapper $vendorFileMapper
28+ * @param DirectoryList $directoryList
29+ * @param ComponentRegistrarInterface $componentRegistrar
30+ * @param File $fileDriver
31+ */
2432 public function __construct (
2533 private readonly ThemeList $ themeList ,
2634 private readonly VendorFileMapper $ vendorFileMapper ,
2735 private readonly DirectoryList $ directoryList ,
28- private readonly ComponentRegistrarInterface $ componentRegistrar
36+ private readonly ComponentRegistrarInterface $ componentRegistrar ,
37+ private readonly File $ fileDriver
2938 ) {
3039 parent ::__construct ();
3140 }
3241
42+ /**
43+ * Configure the command
44+ *
45+ * @return void
46+ */
3347 protected function configure (): void
3448 {
3549 $ this ->setName ('mageforge:theme:copy-from-vendor ' )
@@ -40,6 +54,13 @@ protected function configure(): void
4054 ->addOption ('dry-run ' , null , InputOption::VALUE_NONE , 'Preview the copy operation without performing it ' );
4155 }
4256
57+ /**
58+ * Execute the command
59+ *
60+ * @param InputInterface $input
61+ * @param OutputInterface $output
62+ * @return int
63+ */
4364 protected function executeCommand (InputInterface $ input , OutputInterface $ output ): int
4465 {
4566 $ sourceFileArg = $ input ->getArgument ('file ' );
@@ -73,6 +94,13 @@ protected function executeCommand(InputInterface $input, OutputInterface $output
7394 return Cli::RETURN_SUCCESS ;
7495 }
7596
97+ /**
98+ * Get absolute source path
99+ *
100+ * @param string $sourceFile
101+ * @return string
102+ * @throws \RuntimeException
103+ */
76104 private function getAbsoluteSourcePath (string $ sourceFile ): string
77105 {
78106 $ rootPath = $ this ->directoryList ->getRoot ();
@@ -82,13 +110,20 @@ private function getAbsoluteSourcePath(string $sourceFile): string
82110 $ absoluteSourcePath = $ rootPath . '/ ' . $ sourceFile ;
83111 }
84112
85- if (!file_exists ($ absoluteSourcePath )) {
113+ if (!$ this -> fileDriver -> isExists ($ absoluteSourcePath )) {
86114 throw new \RuntimeException ("Source file not found: $ absoluteSourcePath " );
87115 }
88116
89117 return $ absoluteSourcePath ;
90118 }
91119
120+ /**
121+ * Get theme code
122+ *
123+ * @param InputInterface $input
124+ * @return string
125+ * @throws \RuntimeException
126+ */
92127 private function getThemeCode (InputInterface $ input ): string
93128 {
94129 $ themeCode = $ input ->getArgument ('theme ' );
@@ -136,13 +171,22 @@ private function getThemePathAndArea(string $themeCode): array
136171 $ themePath = $ this ->componentRegistrar ->getPath (ComponentRegistrar::THEME , $ regName );
137172
138173 if (!$ themePath ) {
139- $ this ->io ->warning ("Theme path not found via ComponentRegistrar for $ regName, falling back to getFullPath() " );
174+ $ this ->io ->warning (
175+ "Theme path not found via ComponentRegistrar for $ regName, falling back to getFullPath() "
176+ );
140177 $ themePath = $ theme ->getFullPath ();
141178 }
142179
143180 return [$ themePath , $ themeArea ];
144181 }
145182
183+ /**
184+ * Get absolute destination path
185+ *
186+ * @param string $destinationPath
187+ * @param string $rootPath
188+ * @return string
189+ */
146190 private function getAbsoluteDestPath (string $ destinationPath , string $ rootPath ): string
147191 {
148192 if (str_starts_with ($ destinationPath , '/ ' )) {
@@ -151,6 +195,14 @@ private function getAbsoluteDestPath(string $destinationPath, string $rootPath):
151195 return $ rootPath . '/ ' . $ destinationPath ;
152196 }
153197
198+ /**
199+ * Confirm copy operation
200+ *
201+ * @param string $sourceFile
202+ * @param string $absoluteDestPath
203+ * @param string $rootPath
204+ * @return bool
205+ */
154206 private function confirmCopy (string $ sourceFile , string $ absoluteDestPath , string $ rootPath ): bool
155207 {
156208 $ destinationDisplay = str_starts_with ($ absoluteDestPath , $ rootPath . '/ ' )
@@ -168,7 +220,7 @@ private function confirmCopy(string $sourceFile, string $absoluteDestPath, strin
168220 $ this ->setPromptEnvironment ();
169221
170222 try {
171- if (file_exists ($ absoluteDestPath )) {
223+ if ($ this -> fileDriver -> isExists ($ absoluteDestPath )) {
172224 $ this ->io ->warning ("File already exists at destination! " );
173225 $ result = confirm (
174226 label: 'Overwrite existing file? ' ,
@@ -193,17 +245,31 @@ private function confirmCopy(string $sourceFile, string $absoluteDestPath, strin
193245 }
194246 }
195247
248+ /**
249+ * Perform copy operation
250+ *
251+ * @param string $absoluteSourcePath
252+ * @param string $absoluteDestPath
253+ * @return void
254+ * @throws \RuntimeException
255+ */
196256 private function performCopy (string $ absoluteSourcePath , string $ absoluteDestPath ): void
197257 {
198- $ directory = dirname ($ absoluteDestPath );
199- if (!is_dir ($ directory )) {
200- if (!mkdir ($ directory , 0777 , true ) && !is_dir ($ directory )) {
201- throw new \RuntimeException (sprintf ('Directory "%s" was not created ' , $ directory ));
202- }
258+ $ directory = $ this ->fileDriver ->getParentDirectory ($ absoluteDestPath );
259+ if (!$ this ->fileDriver ->isDirectory ($ directory )) {
260+ $ this ->fileDriver ->createDirectory ($ directory );
203261 }
204- copy ($ absoluteSourcePath , $ absoluteDestPath );
262+ $ this -> fileDriver -> copy ($ absoluteSourcePath , $ absoluteDestPath );
205263 }
206264
265+ /**
266+ * Show dry run preview
267+ *
268+ * @param string $sourceFile
269+ * @param string $absoluteDestPath
270+ * @param string $rootPath
271+ * @return void
272+ */
207273 private function showDryRunPreview (string $ sourceFile , string $ absoluteDestPath , string $ rootPath ): void
208274 {
209275 $ destinationDisplay = str_starts_with ($ absoluteDestPath , $ rootPath . '/ ' )
@@ -218,7 +284,7 @@ private function showDryRunPreview(string $sourceFile, string $absoluteDestPath,
218284 ]);
219285 $ this ->io ->newLine ();
220286
221- if (file_exists ($ absoluteDestPath )) {
287+ if ($ this -> fileDriver -> isExists ($ absoluteDestPath )) {
222288 $ this ->io ->warning ("File already exists at destination and would be overwritten! " );
223289 } else {
224290 $ this ->io ->info ("File would be created at destination. " );
@@ -227,6 +293,11 @@ private function showDryRunPreview(string $sourceFile, string $absoluteDestPath,
227293 $ this ->io ->note ("No files were modified (dry-run mode). " );
228294 }
229295
296+ /**
297+ * Fix prompt environment
298+ *
299+ * @return void
300+ */
230301 private function fixPromptEnvironment (): void
231302 {
232303 $ this ->setPromptEnvironment ();
0 commit comments