Skip to content
This repository was archived by the owner on Oct 6, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/generate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ jobs:
- name: Show PHP version
run: php -v

- name: Install Composer dependencies
run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist

- name: Generate HTML files
run: php generate.php

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/phpstan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
php-version: 8.2

- name: Install Composer dependencies
run: composer update --no-interaction --prefer-dist
run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist

- name: Run tests via PHPStan
run: composer phpstan
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@
# Composer
/vendor/

# PHPUnit
.phpunit.cache

# Generated files
index.html
lang

# Mac OS
.DS_Store
111 changes: 6 additions & 105 deletions generate.php
Original file line number Diff line number Diff line change
@@ -1,110 +1,11 @@
<?php

declare(strict_types=1);

// TODO Add CS-fixer
// TODO Rename file
// TODO To class + ->run()
require_once('./vendor/autoload.php');

use GoodFirstIssue\Generator;
use GoodFirstIssue\GitHubAPIClient;

if (!is_dir('lang')) {
mkdir('lang');
}


// Read the JSON file
$json = file_get_contents('repositories.json');

// Decode the JSON file
$json_data = json_decode($json, true);

// Display data
print_r($json_data);

// TODO Рандомизируем массив с репозиториями

$indexContent = "<h1>Hello!</h1>";

$repositoriesByLanguage = [];

// Проходимся по всем репозиториям
foreach ($json_data as $line) {
echo "Line : https://api.github.com/repos/" . $line . "\n";
// Записываем информацию о репозитории в файл data/repositories.json
// Это необходимо для главной страницы

$opts = [
'http' => [
'method' => 'GET',
'header' => [
'User-Agent: PHP'
]
]
];

$context = stream_context_create($opts);
$repositoryJson = file_get_contents('https://api.github.com/repos/' . $line, false, $context);
$repository = json_decode($repositoryJson, true);

$repositoryData = [
'html_url' => $repository['html_url'], // Ex: "https://github.com/octocat/Hello-World"
'full_name' => $repository['full_name'], // Ex: "octocat/Hello-World"
'description' => $repository['description'], // Ex: "This your first repo!"
'language' => $repository['language'], // Ex: null,
'stargazers_count' => $repository['stargazers_count'], // Ex: 80,
'open_issues_count' => $repository['open_issues_count'], // Ex: 0,
'open_issues' => $repository['open_issues'], // Ex: 0,
'updated_at' => $repository['updated_at'], // Ex: "2011-01-26T19:14:43Z",
];

print_r($repositoryData);

// Конетент для главной страницы
$indexContent .= '<h2>' . $repositoryData['full_name'] . '</h2>';
$indexContent .= '<p>' . $repositoryData['description'] . '</p>';

$repositoriesByLanguage[$repositoryData['language']][] = $repositoryData['full_name'];

// Записываем ищуйки в общий файл
}


file_put_contents('index.html', $indexContent);


foreach ($repositoriesByLanguage as $lang => $repositories) {
if (strlen($lang) < 1) {
$lang = 'other';
}

print_r('Language: ' . $lang);

$langFile = 'lang/' . $lang . '.html';
if (file_exists($langFile)) {
$status = unlink($langFile) ? 'The file ' . $langFile . ' has been deleted' . "\n" : 'Error deleting ' . $langFile . "\n";
echo $status;
}


// TODO Пишем шапку файла
file_put_contents($langFile, '<h1>Lang: ' . $lang . '</h1>' . "\n");

foreach ($repositories as $repository) {
print_r('Repository: ' . $repository."\n");

$issuesJson = file_get_contents('https://api.github.com/repos/' . $repository . '/issues?state=open&sort=updated&labels=good%20first%20issue', false, $context);
$issues = json_decode($issuesJson, true);

foreach ($issues as $issue) {
print_r('Issue #' . $issue['number'] . ' ' . $issue['title'] . "\n");

$str = '<p>' . $issue['title'] . '</p>';
$str .= '<p>' . $issue['html_url'] . '</p>';

file_put_contents($langFile, $str, FILE_APPEND);
}

}


}

$generator = new Generator(__DIR__, new GitHubAPIClient);
$generator->run();
15 changes: 15 additions & 0 deletions src/DTO/Issue.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types = 1);

namespace GoodFirstIssue\DTO;

readonly class Issue
{
public function __construct(
public string $html_url,
public string $title,
public int $number
) {
}
}
43 changes: 43 additions & 0 deletions src/DTO/Repository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

declare(strict_types = 1);

namespace GoodFirstIssue\DTO;

class Repository
{
/**
* @var array<Issue>
*/
private array $issues = [];

public function __construct(
public readonly string $html_url, // Ex: "https://github.com/octocat/Hello-World"
public readonly string $full_name,// Ex: "octocat/Hello-World"
public readonly string $description, // Ex: "This your first repo!"
public readonly string $language, // Ex: null,
public readonly int $stargazers_count, // Ex: 80,
public readonly int $open_issues_count, // Ex: 0,
public readonly int $open_issues, // Ex: 0,
public readonly string $updated_at // Ex: "2011-01-26T19:14:43Z",
) {
}

/**
* @return array<Issue>
*/
public function getIssues(): array
{
return $this->issues;
}

/**
* @param array<Issue> $issues
*
* @return void
*/
public function setIssues(array $issues): void
{
$this->issues = $issues;
}
}
51 changes: 50 additions & 1 deletion src/Generator.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,55 @@

namespace GoodFirstIssue;

class Generator
use GoodFirstIssue\DTO\Repository;
use LogicException;

readonly class Generator
{
public function __construct(
private string $root_path,
private GitHubAPIClient $github_api_client
) {
}

public function run(): void
{
if (! is_dir($this->root_path . '/lang')) {
mkdir($this->root_path . '/lang');
}

// Get repository names from `repositories.json` file
$json = file_get_contents('repositories.json');
if (! is_string($json)) {
throw new LogicException('Cannot read file: repositories.json');
}

$repository_names = json_decode($json, true);
if (! is_array($repository_names)) {
throw new LogicException('Cannot decode repository names');
}

print_r($repository_names);

$repositories = $this->github_api_client->requestRepositoriesData($repository_names);

// TODO сортируем репозитории по updated at

foreach ($repositories as $repository) {
print_r('Get issues for repository: ' . $repository->full_name . "\n");

$issues = $this->github_api_client->requestIssues($repository->full_name);
$repository->setIssues($issues);
}

$renderer = new Renderer($this->root_path);
$renderer->renderIndexPage($repositories);

$repositories_by_language = [];
foreach ($repositories as $repository) {
$repositories_by_language[$repository->language][] = $repository;
}

// TODO $renderer->renderPerLanguagePage($repositories);
}
}
101 changes: 101 additions & 0 deletions src/GitHubAPIClient.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<?php

declare(strict_types = 1);

namespace GoodFirstIssue;

use GoodFirstIssue\DTO\Issue;
use GoodFirstIssue\DTO\Repository;
use LogicException;

readonly class GitHubAPIClient
{
private const OPTS = [
'http' => [
'method' => 'GET',
'header' => ['User-Agent: PHP'],
],
];

/**
* Get information about all repositories.
*
* @param array<string> $repository_names
*
* @return array<Repository>
*/
public function requestRepositoriesData(array $repository_names): array
{
foreach ($repository_names as $repository_name) {
$repository = $this->requestRepositoryData($repository_name);
$repositories[] = $repository;
}

return $repositories ?? [];
}

/**
* @param string $repository_name
*
* @return Repository
*/
public function requestRepositoryData(string $repository_name): Repository
{
$context = stream_context_create(self::OPTS);

$repository_json = file_get_contents($api_route = 'https://api.github.com/repos/' . $repository_name, false, $context);
if (! is_string($repository_json)) {
throw new LogicException('Cannot read GitHub API response from ' . $api_route);
}

$repository = json_decode($repository_json, true);
if (! is_array($repository)) {
throw new LogicException('Cannot decode repository data');
}

$lang = (strlen((string) $repository['language']) < 1) ? 'other' : $repository['language'];

return new Repository(
$repository['html_url'],
$repository['full_name'],
$repository['description'],
$lang,
$repository['stargazers_count'],
$repository['open_issues_count'],
$repository['open_issues'],
$repository['updated_at'],
);
}

/**
* @param string $repository_name
*
* @return array<Issue>
*/
public function requestIssues(string $repository_name): array
{
$context = stream_context_create(self::OPTS);

$issues_json = file_get_contents($api_route = 'https://api.github.com/repos/' . $repository_name . '/issues?state=open&sort=updated&labels=good%20first%20issue', false, $context);
if (! is_string($issues_json)) {
throw new LogicException('Cannot read GitHub API response from ' . $api_route);
}

$issues_data = json_decode($issues_json, true);
if (! is_array($issues_data)) {
throw new LogicException('Cannot decode issues data');
}

foreach ($issues_data as $data) {
print_r('Issue #' . $data['number'] . ' ' . $data['title'] . "\n");

$issues[] = new Issue(
$data['html_url'],
$data['title'],
$data['number']
);
}

return $issues ?? [];
}
}
Loading