Skip to main content
Glama

CTX: Context as Code (CaC) tool

by context-hub
MIT License
235
  • Apple
  • Linux
LocalComposerProvider.php5.83 kB
<?php declare(strict_types=1); namespace Butschster\ContextGenerator\Source\Composer\Provider; use Butschster\ContextGenerator\Lib\ComposerClient\ComposerClientInterface; use Butschster\ContextGenerator\Source\Composer\Package\ComposerPackageCollection; use Butschster\ContextGenerator\Source\Composer\Package\ComposerPackageInfo; use Psr\Log\LoggerInterface; use Psr\Log\NullLogger; final readonly class LocalComposerProvider extends AbstractComposerProvider { public function __construct( ComposerClientInterface $client, private string $basePath = '.', LoggerInterface $logger = new NullLogger(), ) { parent::__construct($client, $logger); } /** * Get packages from a local Composer project * * @param string $composerPath Path to composer.json or directory containing it * @param bool $includeDevDependencies Whether to include dev dependencies * @return ComposerPackageCollection Collection of packages */ public function getPackages(string $composerPath, bool $includeDevDependencies = false): ComposerPackageCollection { $this->logger->info('Getting packages from local composer project', [ 'composerPath' => $composerPath, 'includeDevDependencies' => $includeDevDependencies, ]); // Load and parse composer.json $composerData = $this->client->loadComposerData($composerPath); // Try to load composer.lock for more accurate version information $lockData = $this->client->tryLoadComposerLock(\dirname($this->basePath . '/composer.json')); $packageVersions = $this->extractPackageVersionsFromLock($lockData, $includeDevDependencies); // Get vendor directory $vendorDir = $this->client->getVendorDir($composerData, $this->basePath); // Create package collection $packages = new ComposerPackageCollection(); // Process regular dependencies $this->processPackages( $packages, $composerData['require'] ?? [], $packageVersions, $vendorDir, ); // Process dev dependencies if requested if ($includeDevDependencies && isset($composerData['require-dev']) && \is_array($composerData['require-dev'])) { $this->processPackages( $packages, $composerData['require-dev'], $packageVersions, $vendorDir, true, ); } $this->logger->info('Found packages', [ 'count' => $packages->count(), ]); return $packages; } /** * Process packages and add them to the collection * * @param ComposerPackageCollection $packages The collection to add packages to * @param array<string, string> $dependencies The dependencies from composer.json * @param array<string, array<string, mixed>> $packageVersions Versions from composer.lock * @param string $vendorDir Vendor directory path * @param bool $isDev Whether these are dev dependencies */ private function processPackages( ComposerPackageCollection $packages, array $dependencies, array $packageVersions, string $vendorDir, bool $isDev = false, ): void { foreach ($dependencies as $packageName => $constraintVersion) { // Skip php and ext-* dependencies if ($packageName === 'php' || \str_starts_with($packageName, 'ext-')) { continue; } // Skip if already included in regular dependencies (for dev deps) if ($isDev && $packages->has($packageName)) { continue; } $packagePath = $this->basePath . '/' . $vendorDir . '/' . $packageName; if (!\is_dir($packagePath)) { $this->logger->warning('Package directory not found', [ 'package' => $packageName, 'path' => $packagePath, 'isDev' => $isDev, ]); continue; } // Get actual version from lock file if available $version = $packageVersions[$packageName]['version'] ?? $constraintVersion; $extraData = $packageVersions[$packageName] ?? []; // Try to load package's composer.json try { $packageComposerData = $this->client->loadComposerData($packagePath); // If we have extra data from lock file, merge it with composer.json if (!empty($extraData) && isset($extraData['description'])) { $packageComposerData['description'] ??= $extraData['description']; } $packages->add( new ComposerPackageInfo( name: $packageName, path: $packagePath, version: $version, composerConfig: $packageComposerData, ), ); } catch (\Throwable $e) { $this->logger->warning('Failed to load package composer.json', [ 'package' => $packageName, 'path' => $packagePath, 'error' => $e->getMessage(), 'isDev' => $isDev, ]); // Add the package with minimal info $packages->add( new ComposerPackageInfo( name: $packageName, path: $packagePath, version: $version, composerConfig: ['description' => $extraData['description'] ?? ''], ), ); } } } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/context-hub/generator'

If you have feedback or need assistance with the MCP directory API, please join our Discord server