33namespace Neuron \Cli \Commands \Core ;
44
55use Neuron \Cli \Commands \Command ;
6+ use Neuron \Core \System \IFileSystem ;
7+ use Neuron \Core \System \RealFileSystem ;
68
79/**
810 * Version command - displays version information for Neuron components
911 */
1012class VersionCommand extends Command
1113{
14+ private IFileSystem $ fs ;
15+
16+ /**
17+ * @param IFileSystem|null $fs File system implementation (null = use real file system)
18+ */
19+ public function __construct ( ?IFileSystem $ fs = null )
20+ {
21+ $ this ->fs = $ fs ?? new RealFileSystem ();
22+ }
23+
1224 /**
1325 * @inheritDoc
1426 */
@@ -159,57 +171,68 @@ private function showComponentVersion( string $componentName ): void
159171
160172 /**
161173 * Get the CLI component version
162- *
174+ *
163175 * @return string
164176 */
165177 private function getCliVersion (): string
166178 {
167179 $ composerJson = dirname ( __DIR__ , 4 ) . '/composer.json ' ;
168-
169- if ( file_exists ( $ composerJson ) )
180+
181+ if ( $ this -> fs -> fileExists ( $ composerJson ) )
170182 {
171- $ composer = json_decode ( file_get_contents ( $ composerJson ), true );
172- return $ composer ['version ' ] ?? '0.1.0 ' ;
183+ $ content = $ this ->fs ->readFile ( $ composerJson );
184+ if ( $ content !== false )
185+ {
186+ $ composer = json_decode ( $ content , true );
187+ return $ composer ['version ' ] ?? '0.1.0 ' ;
188+ }
173189 }
174-
190+
175191 return '0.1.0 ' ;
176192 }
177193
178194 /**
179195 * Get information about installed Neuron components
180- *
196+ *
181197 * @return array
182198 */
183199 private function getInstalledComponents (): array
184200 {
185201 $ components = [];
186-
202+
187203 // Find vendor directory
188204 $ vendorDir = $ this ->findVendorDirectory ();
189-
205+
190206 if ( !$ vendorDir )
191207 {
192208 return $ components ;
193209 }
194-
210+
195211 // Load from composer's installed.json
196212 $ installedJson = $ vendorDir . '/composer/installed.json ' ;
197-
198- if ( !file_exists ( $ installedJson ) )
213+
214+ if ( !$ this -> fs -> fileExists ( $ installedJson ) )
199215 {
200216 return $ components ;
201217 }
202-
203- $ installed = json_decode ( file_get_contents ( $ installedJson ), true );
204-
218+
219+ $ content = $ this ->fs ->readFile ( $ installedJson );
220+
221+ if ( $ content === false )
222+ {
223+ return $ components ;
224+ }
225+
226+ $ installed = json_decode ( $ content , true );
227+
205228 if ( !$ installed )
206229 {
207230 return $ components ;
208231 }
209-
232+
210233 // Handle both composer 1.x and 2.x formats
211234 $ packages = isset ( $ installed ['packages ' ] ) ? $ installed ['packages ' ] : $ installed ;
212-
235+
213236 foreach ( $ packages as $ package )
214237 {
215238 // Only include neuron-php packages
@@ -218,35 +241,37 @@ private function getInstalledComponents(): array
218241 $ components [$ package ['name ' ]] = $ package ;
219242 }
220243 }
221-
244+
222245 // Sort by name
223246 ksort ( $ components );
224-
247+
225248 return $ components ;
226249 }
227250
228251 /**
229252 * Find the vendor directory
230- *
253+ *
231254 * @return string|null
232255 */
233256 private function findVendorDirectory (): ?string
234257 {
258+ $ cwd = $ this ->fs ->getcwd ();
259+
235260 $ locations = [
236261 dirname ( __DIR__ , 4 ) . '/vendor ' ,
237262 dirname ( __DIR__ , 5 ) . '/vendor ' ,
238- getcwd () . '/vendor ' ,
263+ $ cwd . '/vendor ' ,
239264 ];
240-
265+
241266 foreach ( $ locations as $ location )
242267 {
243- $ path = realpath ( $ location );
244- if ( $ path && is_dir ( $ path ) )
268+ $ path = $ this -> fs -> realpath ( $ location );
269+ if ( $ path && $ this -> fs -> isDir ( $ path ) )
245270 {
246271 return $ path ;
247272 }
248273 }
249-
274+
250275 return null ;
251276 }
252277}
0 commit comments