/** * @param string $composerJsonFileContent * @param string $composerLockFileContent * @param string $installedFileDevContent * @param string $installedFileContent * * @throws \RuntimeException * @throws \InvalidArgumentException * @return \JMS\Composer\Graph\DependencyGraph */ public function analyze($composerJsonFileContent, $composerLockFileContent, $installedFileContent, $installedFileDevContent = null, $connectRequireDev = false) { $json = new Json(); $rootPackageData = $json->decode($composerJsonFileContent, true); if (!isset($rootPackageData['name'])) { $rootPackageData['name'] = '__root'; } // If there is no composer.lock file, then either the project has no // dependencies, or the dependencies were not installed. if (empty($composerLockFileContent)) { if ($this->hasDependencies($rootPackageData)) { throw new \RuntimeException(sprintf('You need to run "composer install" in "%s" before analyzing dependencies.', $dir)); } $graph = new DependencyGraph(new PackageNode($rootPackageData['name'], $rootPackageData)); // Connect built-in dependencies for example on the PHP version, or // on PHP extensions. For these, composer does not create a composer.lock. if (isset($rootPackageData['require'])) { foreach ($rootPackageData['require'] as $name => $versionConstraint) { $this->connect($graph, $rootPackageData['name'], $name, $versionConstraint); } } if ($connectRequireDev && isset($rootPackageData['require-dev'])) { foreach ($rootPackageData['require-dev'] as $name => $versionConstraint) { $this->connect($graph, $rootPackageData['name'], $name, $versionConstraint); } } return $graph; } $graph = new DependencyGraph(new PackageNode($rootPackageData['name'], $rootPackageData)); // Add regular packages. if (!empty($installedFileContent)) { foreach ($json->decode($installedFileContent, true) as $packageData) { $graph->createPackage($packageData['name'], $packageData); $this->processLockedData($graph, $packageData); } } // Add development packages. if ($connectRequireDev && !empty($installedFileDevContent)) { foreach ($json->decode($installedFileDevContent, true) as $packageData) { $graph->createPackage($packageData['name'], $packageData); $this->processLockedData($graph, $packageData); } } // Connect dependent packages. foreach ($graph->getPackages() as $packageNode) { $packageData = $packageNode->getData(); if (isset($packageData['require'])) { foreach ($packageData['require'] as $name => $version) { $this->connect($graph, $packageData['name'], $name, $version); } } if ($connectRequireDev && isset($packageData['require-dev'])) { foreach ($packageData['require-dev'] as $name => $version) { $this->connect($graph, $packageData['name'], $name, $version); } } } // Populate graph with versions, and source references. $lockData = $json->decode($composerLockFileContent, true); if (isset($lockData['packages'])) { foreach ($lockData['packages'] as $lockedPackageData) { $this->processLockedData($graph, $lockedPackageData); } } if ($connectRequireDev && isset($lockData['packages-dev'])) { foreach ($lockData['packages-dev'] as $lockedPackageData) { $this->processLockedData($graph, $lockedPackageData); } } return $graph; }
private function addPackages(DependencyGraph $graph, array $packages, $vendorDir) { foreach ($packages as $packageData) { if ($graph->isRootPackageName($packageData['name']) || $graph->hasPackage($packageData['name'])) { continue; } $package = $graph->createPackage($packageData['name'], $packageData); $package->setAttribute('dir', $vendorDir . '/' . $packageData['name']); $this->processLockedData($graph, $packageData); } }