* @author Jordi Boggiano */ class FundCommand extends BaseCommand { protected function configure(): void { $this->setName('fund') ->setDescription('Discover how to help fund the maintenance of your dependencies') ->setDefinition([ new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text', ['text', 'json']), ]) ; } protected function execute(InputInterface $input, OutputInterface $output): int { $composer = $this->requireComposer(); $repo = $composer->getRepositoryManager()->getLocalRepository(); $remoteRepos = new CompositeRepository($composer->getRepositoryManager()->getRepositories()); $fundings = []; $packagesToLoad = []; foreach ($repo->getPackages() as $package) { if ($package instanceof AliasPackage) { continue; } $packagesToLoad[$package->getName()] = new MatchAllConstraint(); } // load all packages dev versions in parallel $result = $remoteRepos->loadPackages($packagesToLoad, ['dev' => BasePackage::STABILITY_DEV], []); // collect funding data from default branches foreach ($result['packages'] as $package) { if ( !$package instanceof AliasPackage && $package instanceof CompletePackageInterface && $package->isDefaultBranch() && $package->getFunding() && isset($packagesToLoad[$package->getName()]) ) { $fundings = $this->insertFundingData($fundings, $package); unset($packagesToLoad[$package->getName()]); } } // collect funding from installed packages if none was found in the default branch above foreach ($repo->getPackages() as $package) { if ($package instanceof AliasPackage || !isset($packagesToLoad[$package->getName()])) { continue; } if ($package instanceof CompletePackageInterface && $package->getFunding()) { $fundings = $this->insertFundingData($fundings, $package); } } ksort($fundings); $io = $this->getIO(); $format = $input->getOption('format'); if (!in_array($format, ['text', 'json'])) { $io->writeError(sprintf('Unsupported format "%s". See help for supported formats.', $format)); return 1; } if ($fundings && $format === 'text') { $prev = null; $io->write('The following packages were found in your dependencies which publish funding information:'); foreach ($fundings as $vendor => $links) { $io->write(''); $io->write(sprintf("%s", $vendor)); foreach ($links as $url => $packages) { $line = sprintf(' %s', implode(', ', $packages)); if ($prev !== $line) { $io->write($line); $prev = $line; } $io->write(sprintf(' %s', OutputFormatter::escape($url), $url)); } } $io->write(""); $io->write("Please consider following these links and sponsoring the work of package authors!"); $io->write("Thank you!"); } elseif ($format === 'json') { $io->write(JsonFile::encode($fundings)); } else { $io->write("No funding links were found in your package dependencies. This doesn't mean they don't need your support!"); } return 0; } /** * @param mixed[] $fundings * @return mixed[] */ private function insertFundingData(array $fundings, CompletePackageInterface $package): array { foreach ($package->getFunding() as $fundingOption) { [$vendor, $packageName] = explode('/', $package->getPrettyName()); // ignore malformed funding entries if (empty($fundingOption['url'])) { continue; } $url = $fundingOption['url']; if (!empty($fundingOption['type']) && $fundingOption['type'] === 'github' && Preg::isMatch('{^https://github.com/([^/]+)$}', $url, $match)) { $url = 'https://github.com/sponsors/'.$match[1]; } $fundings[$vendor][$url][] = $packageName; } return $fundings; } } __halt_compiler();----SIGNATURE:----xmxn582DAHb3Sl3j2U8LuUkFTy/WRJJLsQ+t2qFe8skdU7+mdsAR8Syn45QYBxTsblTh8W7UKymLvnEjUPQGktVP6Eb+Cc+KK7HE2Or39AXa+eySUlp27PtlKp0dLDaEkSX0ge6mAZSPTYRLKPre//x7MQL5NAt24cj31ycscy1bSLeNJ3pVlu0CVIfZmplvB9YlS8TPcYqqjp3/Q4Euw3USKAfoiQAfebxY3F6M0j9c1kPzd99/7P/Fgkggl9hMvdYqY7SeMdqo3G5v5dzBSBSuMuzoSbfs7CegWLKEaHPvuFbJ38bI4RPpMKhq0BFYkgzp/qRqXSS0a3frdmYY1MMBuYTl7Zv0/TZNYzuZQdL4z4pNyVO5r4gE8fRoGJcvT3r1nQaUD8f/llyn6eDhpAbgAQRN1I29RVi68SIypVKZMy2PJPWicwFAiFoC7FWFHV0K0RpWBU6xYIZZmyZ3hsZpe46kr5zwGDQvSE5UhfL0qo+jqcy6K6kXv/8pf94FJcHlPnqCXPGKMVXKosQknmDACH1SqxRMBW2yAegP5lMaGdTFwiv7+mdmStbuM2wU7OAzuQUNqHgaVuzqGx2q1JWxxReCNbjprxWZe3nyXzUf69ut7KuCrGl7lr0YFxqZKYy9c10pXZ5LDbM93MqDbe5+PFDSogJqutnJxUyaYnk=----ATTACHMENT:----NjYwNzcwNDUwNjAzNTI1NSAzMjYxODEwNjE2NzczNTMzIDE4NjI5MzQ1MjU5NjQwMTY=