sonarrradarrplexorganizrnginxdashboardmuximuxlandingpagestartpagelandinghtpcserverhomepagesabnzbdheimdallembycouchpotatonzbgetbookmarkapplication-dashboard
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
227 lines
7.6 KiB
227 lines
7.6 KiB
<?php
|
|
|
|
/*
|
|
* This file is part of the Symfony package.
|
|
*
|
|
* (c) Fabien Potencier <fabien@symfony.com>
|
|
*
|
|
* For the full copyright and license information, please view the LICENSE
|
|
* file that was distributed with this source code.
|
|
*/
|
|
|
|
namespace Symfony\Thanks;
|
|
|
|
use Composer\Composer;
|
|
use Composer\Downloader\TransportException;
|
|
use Composer\Factory;
|
|
use Composer\IO\IOInterface;
|
|
use Composer\Json\JsonFile;
|
|
use Composer\Plugin\PluginEvents;
|
|
use Composer\Plugin\PreFileDownloadEvent;
|
|
use Hirak\Prestissimo\CurlRemoteFilesystem;
|
|
|
|
/**
|
|
* @author Nicolas Grekas <p@tchwork.com>
|
|
*/
|
|
class GitHubClient
|
|
{
|
|
// This is a list of projects that should get a star on their main repository
|
|
// (when there is one) whenever you use any of their other repositories.
|
|
// When a project's main repo is also a dependency of their other repos (like amphp/amp),
|
|
// there is no need to list it here, as starring will transitively happen anyway.
|
|
private static $mainRepositories = [
|
|
'api-platform' => [
|
|
'name' => 'api-platform/api-platform',
|
|
'url' => 'https://github.com/api-platform/api-platform',
|
|
],
|
|
'cakephp' => [
|
|
'name' => 'cakephp/cakephp',
|
|
'url' => 'https://github.com/cakephp/cakephp',
|
|
],
|
|
'drupal' => [
|
|
'name' => 'drupal/drupal',
|
|
'url' => 'https://github.com/drupal/drupal',
|
|
],
|
|
'laravel' => [
|
|
'name' => 'laravel/laravel',
|
|
'url' => 'https://github.com/laravel/laravel',
|
|
],
|
|
'illuminate' => [
|
|
'name' => 'laravel/laravel',
|
|
'url' => 'https://github.com/laravel/laravel',
|
|
],
|
|
'nette' => [
|
|
'name' => 'nette/nette',
|
|
'url' => 'https://github.com/nette/nette',
|
|
],
|
|
'phpDocumentor' => [
|
|
'name' => 'phpDocumentor/phpDocumentor2',
|
|
'url' => 'https://github.com/phpDocumentor/phpDocumentor2',
|
|
],
|
|
'piwik' => [
|
|
'name' => 'piwik/piwik',
|
|
'url' => 'https://github.com/piwik/piwik',
|
|
],
|
|
'reactphp' => [
|
|
'name' => 'reactphp/react',
|
|
'url' => 'https://github.com/reactphp/react',
|
|
],
|
|
'sebastianbergmann' => [
|
|
'name' => 'phpunit/phpunit',
|
|
'url' => 'https://github.com/sebastianbergmann/phpunit',
|
|
],
|
|
'slimphp' => [
|
|
'name' => 'slimphp/Slim',
|
|
'url' => 'https://github.com/slimphp/Slim',
|
|
],
|
|
'Sylius' => [
|
|
'name' => 'Sylius/Sylius',
|
|
'url' => 'https://github.com/Sylius/Sylius',
|
|
],
|
|
'symfony' => [
|
|
'name' => 'symfony/symfony',
|
|
'url' => 'https://github.com/symfony/symfony',
|
|
],
|
|
'yiisoft' => [
|
|
'name' => 'yiisoft/yii2',
|
|
'url' => 'https://github.com/yiisoft/yii2',
|
|
],
|
|
'zendframework' => [
|
|
'name' => 'zendframework/zendframework',
|
|
'url' => 'https://github.com/zendframework/zendframework',
|
|
],
|
|
];
|
|
|
|
private $composer;
|
|
private $io;
|
|
private $rfs;
|
|
|
|
public function __construct(Composer $composer, IOInterface $io)
|
|
{
|
|
$this->composer = $composer;
|
|
$this->io = $io;
|
|
$this->rfs = Factory::createRemoteFilesystem($io, $composer->getConfig());
|
|
}
|
|
|
|
public function getRepositories(array &$failures = null)
|
|
{
|
|
$repo = $this->composer->getRepositoryManager()->getLocalRepository();
|
|
|
|
$urls = [
|
|
'composer/composer' => 'https://github.com/composer/composer',
|
|
'php/php-src' => 'https://github.com/php/php-src',
|
|
'symfony/thanks' => 'https://github.com/symfony/thanks',
|
|
];
|
|
|
|
$directPackages = $this->getDirectlyRequiredPackageNames();
|
|
// symfony/thanks shouldn't trigger thanking symfony/symfony
|
|
unset($directPackages['symfony/thanks']);
|
|
foreach ($repo->getPackages() as $package) {
|
|
$extra = $package->getExtra();
|
|
|
|
if (isset($extra['thanks']['name'], $extra['thanks']['url'])) {
|
|
$urls += [$extra['thanks']['name'] => $extra['thanks']['url']];
|
|
}
|
|
|
|
if (!$url = $package->getSourceUrl()) {
|
|
continue;
|
|
}
|
|
|
|
$urls[$package->getName()] = $url;
|
|
|
|
if (!preg_match('#^https://github.com/([^/]++)#', $url, $url)) {
|
|
continue;
|
|
}
|
|
$owner = $url[1];
|
|
|
|
// star the main repository, but only if this package is directly
|
|
// being required by the user's composer.json
|
|
if (isset(self::$mainRepositories[$owner], $directPackages[$package->getName()])) {
|
|
$urls[self::$mainRepositories[$owner]['name']] = self::$mainRepositories[$owner]['url'];
|
|
}
|
|
}
|
|
|
|
ksort($urls);
|
|
|
|
$i = 0;
|
|
$template = '_%d: repository(owner:"%s",name:"%s"){id,viewerHasStarred}'."\n";
|
|
$graphql = '';
|
|
|
|
foreach ($urls as $package => $url) {
|
|
if (preg_match('#^https://github.com/([^/]++)/(.*?)(?:\.git)?$#i', $url, $url)) {
|
|
$graphql .= sprintf($template, ++$i, $url[1], $url[2]);
|
|
$aliases['_'.$i] = [$package, $url[0]];
|
|
}
|
|
}
|
|
|
|
$failures = [];
|
|
$repos = [];
|
|
|
|
foreach ($this->call(sprintf("query{\n%s}", $graphql), $failures) as $alias => $repo) {
|
|
$repo['package'] = $aliases[$alias][0];
|
|
$repo['url'] = $aliases[$alias][1];
|
|
$repos[$alias] = $repo;
|
|
}
|
|
|
|
foreach ($failures as $alias => $messages) {
|
|
$failures[$alias] = [
|
|
'messages' => $messages,
|
|
'package' => $aliases[$alias][0],
|
|
'url' => $aliases[$alias][1],
|
|
];
|
|
}
|
|
|
|
return $repos;
|
|
}
|
|
|
|
public function call($graphql, array &$failures = [])
|
|
{
|
|
$rfs = $this->rfs;
|
|
|
|
if ($eventDispatcher = $this->composer->getEventDispatcher()) {
|
|
$preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $rfs, 'https://api.github.com/graphql');
|
|
$eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
|
|
if (!$preFileDownloadEvent->getRemoteFilesystem() instanceof CurlRemoteFilesystem) {
|
|
$rfs = $preFileDownloadEvent->getRemoteFilesystem();
|
|
}
|
|
}
|
|
|
|
$result = $rfs->getContents('github.com', 'https://api.github.com/graphql', false, [
|
|
'http' => [
|
|
'method' => 'POST',
|
|
'content' => json_encode(['query' => $graphql]),
|
|
'header' => ['Content-Type: application/json'],
|
|
],
|
|
]);
|
|
$result = json_decode($result, true);
|
|
|
|
if (isset($result['errors'][0]['message'])) {
|
|
if (!$result['data']) {
|
|
throw new TransportException($result['errors'][0]['message']);
|
|
}
|
|
|
|
foreach ($result['errors'] as $error) {
|
|
foreach ($error['path'] as $path) {
|
|
$failures += [$path => $error['message']];
|
|
unset($result['data'][$path]);
|
|
}
|
|
}
|
|
}
|
|
|
|
return $result['data'];
|
|
}
|
|
|
|
private function getDirectlyRequiredPackageNames()
|
|
{
|
|
$file = new JsonFile(Factory::getComposerFile(), null, $this->io);
|
|
|
|
if (!$file->exists()) {
|
|
throw new \Exception('Could not find your composer.json file!');
|
|
}
|
|
|
|
$data = $file->read() + ['require' => [], 'require-dev' => []];
|
|
$data = array_keys($data['require'] + $data['require-dev']);
|
|
|
|
return array_combine($data, $data);
|
|
}
|
|
}
|
|
|