|
11 | 11 |
|
12 | 12 | namespace Symfony\AI\Mate\Discovery; |
13 | 13 |
|
| 14 | +use Composer\InstalledVersions; |
14 | 15 | use Psr\Log\LoggerInterface; |
15 | 16 |
|
16 | 17 | /** |
@@ -161,64 +162,13 @@ private function getInstalledPackages(): array |
161 | 162 | return $this->installedPackages; |
162 | 163 | } |
163 | 164 |
|
164 | | - $installedJsonPath = $this->rootDir.'/vendor/composer/installed.json'; |
165 | | - if (!file_exists($installedJsonPath)) { |
166 | | - $this->logger->warning('Composer installed.json not found', ['path' => $installedJsonPath]); |
167 | | - |
168 | | - return $this->installedPackages = []; |
| 165 | + if (method_exists(InstalledVersions::class, 'getAllRawData')) { |
| 166 | + $packages = InstalledVersions::getAllRawData(); |
| 167 | + } else { |
| 168 | + $packages = $this->getPackagesWithoutComposer(); |
169 | 169 | } |
170 | 170 |
|
171 | | - $content = file_get_contents($installedJsonPath); |
172 | | - if (false === $content) { |
173 | | - $this->logger->warning('Could not read installed.json', [ |
174 | | - 'path' => $installedJsonPath, |
175 | | - 'error' => error_get_last()['message'] ?? 'Unknown error', |
176 | | - ]); |
177 | | - |
178 | | - return $this->installedPackages = []; |
179 | | - } |
180 | | - |
181 | | - try { |
182 | | - $data = json_decode($content, true, 512, \JSON_THROW_ON_ERROR); |
183 | | - } catch (\JsonException $e) { |
184 | | - $this->logger->error('Invalid JSON in installed.json', ['error' => $e->getMessage()]); |
185 | | - |
186 | | - return $this->installedPackages = []; |
187 | | - } |
188 | | - |
189 | | - if (!\is_array($data)) { |
190 | | - return $this->installedPackages = []; |
191 | | - } |
192 | | - |
193 | | - // Handle both formats: {"packages": [...]} and direct array |
194 | | - $packages = $data['packages'] ?? $data; |
195 | | - if (!\is_array($packages)) { |
196 | | - return $this->installedPackages = []; |
197 | | - } |
198 | | - |
199 | | - $indexed = []; |
200 | | - foreach ($packages as $package) { |
201 | | - if (!\is_array($package) || !isset($package['name']) || !\is_string($package['name'])) { |
202 | | - continue; |
203 | | - } |
204 | | - |
205 | | - /** @var array{ |
206 | | - * name: string, |
207 | | - * extra: array<string, mixed>, |
208 | | - * } $validPackage */ |
209 | | - $validPackage = [ |
210 | | - 'name' => $package['name'], |
211 | | - 'extra' => [], |
212 | | - ]; |
213 | | - |
214 | | - if (isset($package['extra']) && \is_array($package['extra'])) { |
215 | | - /** @var array<string, mixed> $extra */ |
216 | | - $extra = $package['extra']; |
217 | | - $validPackage['extra'] = $extra; |
218 | | - } |
219 | | - |
220 | | - $indexed[$package['name']] = $validPackage; |
221 | | - } |
| 171 | + $indexed = $this->indexPackagesByName($packages); |
222 | 172 |
|
223 | 173 | return $this->installedPackages = $indexed; |
224 | 174 | } |
@@ -420,4 +370,75 @@ private function extractAiMateConfigString(array $composer, string $key): ?strin |
420 | 370 |
|
421 | 371 | return $value; |
422 | 372 | } |
| 373 | + |
| 374 | + private function getPackagesWithoutComposer(): array |
| 375 | + { |
| 376 | + $installedJsonPath = $this->rootDir.'/vendor/composer/installed.json'; |
| 377 | + |
| 378 | + if (!file_exists($installedJsonPath)) { |
| 379 | + $this->logger->warning('Composer installed.json not found', ['path' => $installedJsonPath]); |
| 380 | + |
| 381 | + return []; |
| 382 | + } |
| 383 | + |
| 384 | + $content = file_get_contents($installedJsonPath); |
| 385 | + if (false === $content) { |
| 386 | + $this->logger->warning('Could not read installed.json', [ |
| 387 | + 'path' => $installedJsonPath, |
| 388 | + 'error' => error_get_last()['message'] ?? 'Unknown error', |
| 389 | + ]); |
| 390 | + |
| 391 | + return []; |
| 392 | + } |
| 393 | + |
| 394 | + try { |
| 395 | + $data = json_decode($content, true, 512, \JSON_THROW_ON_ERROR); |
| 396 | + } catch (\JsonException $e) { |
| 397 | + $this->logger->error('Invalid JSON in installed.json', ['error' => $e->getMessage()]); |
| 398 | + |
| 399 | + return []; |
| 400 | + } |
| 401 | + |
| 402 | + if (!\is_array($data)) { |
| 403 | + return []; |
| 404 | + } |
| 405 | + |
| 406 | + // Handle both formats: {"packages": [...]} and direct array |
| 407 | + $packages = $data['packages'] ?? $data; |
| 408 | + |
| 409 | + if (!\is_array($packages)) { |
| 410 | + return []; |
| 411 | + } |
| 412 | + |
| 413 | + return $packages; |
| 414 | + } |
| 415 | + |
| 416 | + private function indexPackagesByName(array $packages): array |
| 417 | + { |
| 418 | + $indexed = []; |
| 419 | + foreach ($packages as $package) { |
| 420 | + if (!\is_array($package) || !isset($package['name']) || !\is_string($package['name'])) { |
| 421 | + continue; |
| 422 | + } |
| 423 | + |
| 424 | + /** @var array{ |
| 425 | + * name: string, |
| 426 | + * extra: array<string, mixed>, |
| 427 | + * } $validPackage |
| 428 | + */ |
| 429 | + $validPackage = [ |
| 430 | + 'name' => $package['name'], |
| 431 | + 'extra' => [], |
| 432 | + ]; |
| 433 | + |
| 434 | + if (isset($package['extra']) && \is_array($package['extra'])) { |
| 435 | + /** @var array<string, mixed> $extra */ |
| 436 | + $extra = $package['extra']; |
| 437 | + $validPackage['extra'] = $extra; |
| 438 | + } |
| 439 | + |
| 440 | + $indexed[$package['name']] = $validPackage; |
| 441 | + } |
| 442 | + return $indexed; |
| 443 | + } |
423 | 444 | } |
0 commit comments