Skip to content

Commit

Permalink
Add changelog / requirement / install .. for every package
Browse files Browse the repository at this point in the history
  • Loading branch information
smnandre authored and Kocal committed Aug 15, 2024
1 parent 2e6a24c commit 9bd4ca5
Show file tree
Hide file tree
Showing 6 changed files with 307 additions and 5 deletions.
41 changes: 40 additions & 1 deletion ux.symfony.com/src/Controller/ChangelogController.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
namespace App\Controller;

use App\Service\Changelog\ChangelogProvider;
use App\Service\Packagist\PackagistDataProvider;
use App\Service\UxPackageRepository;
use App\Twig\Components\ChangelogItem;
use DateTimeImmutable;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
Expand All @@ -20,7 +24,8 @@ class ChangelogController extends AbstractController
{
public function __construct(
private readonly ChangelogProvider $changeLogProvider,
) {
)
{
}

#[Route('/changelog', name: 'app_changelog')]
Expand All @@ -32,4 +37,38 @@ public function __invoke(): Response
'changelog' => $changelog,
]);
}

#[Route('/{package}/changelog', name: 'app_changelog_package')]
public function package(string $package, UxPackageRepository $packageRepository, PackagistDataProvider $packagistData): Response
{
$uxPackage = $packageRepository->find($package);

$packageLog = $this->changeLogProvider->getPackageChangelog('ux-'.$uxPackage->getName());
$packageData = $packagistData->getPackageData($uxPackage->getComposerName());

$firstLine = array_shift($packageLog);

$changelog = [];
foreach ($packageLog as $a) {
$lines = explode("\n", $a);
$version = array_shift($lines);

$versionData = $packageData['versions']['v'.$version] ?? [];
if ([] === $versionData) {
continue;
}

$changelog[] = [
'body' => implode("\n", $lines),
'version' => $version,
'name' => 'v'.$version,
'date' => $versionData['time'] ?? null,
];
}

return $this->render('ux_packages/package_changelog.html.twig', [
'package' => $uxPackage,
'changelog' => $changelog,
]);
}
}
87 changes: 87 additions & 0 deletions ux.symfony.com/src/Controller/UxPackageController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace App\Controller;

use App\Service\Changelog\ChangelogProvider;
use App\Service\Packagist\PackagistDataProvider;
use App\Service\UxPackageRepository;
use App\Twig\Components\ChangelogItem;
use DateTimeImmutable;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;

#[Route('/{package}', name: 'app_package')]
class UxPackageController extends AbstractController
{
public function __construct(
private readonly UxPackageRepository $packageRepository,
private readonly ChangelogProvider $changeLogProvider,
private readonly PackagistDataProvider $packagistData,
)
{
}

#[Route('/changelog', name: 'app_package_changelog')]
public function changelog(string $package): Response
{
$uxPackage = $this->packageRepository->find($package) ?? throw $this->createNotFoundException(sprintf('Package "%s" not found', $package));

$packageLog = $this->changeLogProvider->getPackageChangelog('ux-'.$uxPackage->getName());
$packageData = $this->packagistData->getPackageData($uxPackage->getComposerName());

$firstLine = array_shift($packageLog);

$changelog = [];
foreach ($packageLog as $a) {

$lines = explode("\n", $a);
$version = array_shift($lines);

$versionData = $packageData['versions']['v'.$version] ?? [];
if ([] === $versionData) {
continue;
}

$changelog[] = [
'body' => implode("\n", $lines),
'version' => $version,
'name' => 'v'.$version,
'date' => $versionData['time'] ?? null,
];
}

return $this->render('ux_packages/package_changelog.html.twig', [
'package' => $uxPackage,
'changelog' => $changelog,
]);
}

#[Route('/requirements', name: 'app_package_requirements')]
public function requirements(string $package): Response
{
$uxPackage = $this->packageRepository->find($package) ?? throw $this->createNotFoundException(sprintf('Package "%s" not found', $package));

$packageData = $this->packagistData->getPackageData($uxPackage->getComposerName());

$packageVersions = $packageData['versions'] ?? [];
$currentVersion = array_shift($packageVersions);

return $this->render('ux_packages/package_requirements.html.twig', [
'package' => $uxPackage,
'requirements' => [
'requires' => $currentVersion['require'] ?? [],
'devRequires' => $currentVersion['require-dev'] ?? [],
],
]);
}
}
36 changes: 32 additions & 4 deletions ux.symfony.com/src/Service/Changelog/ChangelogProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,48 @@ public function getChangelog(int $page = 1): array
{
$changelog = [];

foreach ($this->getReleases($page) as $release) {
foreach ($this->getReleases('ux', $page) as $release) {
$changelog[] = $release;
}

return $changelog;
}

private function getReleases(int $page = 1): array
public function getPackageChangelog(string $repo, int $page = 1): array
{
return $this->cache->get('releases-symfony-ux-'.$page, function (CacheItemInterface $item) use ($page) {
$changelogMd = $this->cache->get('changelog-symfony-'.$repo.'-'.$page, function (CacheItemInterface $item) use ($repo, $page) {
$item->expiresAfter(604800); // 1 week

return $this->fetchReleases('symfony', 'ux', $page);
return $this->fetchPackageChangelog('symfony', $repo, $page);
});

$changelog = [];
$changelogMarkdown = explode("\n## ", $changelogMd);

return $changelogMarkdown;
}

private function getReleases(string $repo, int $page = 1): array
{
return $this->cache->get('releases-symfony-'.$repo.'-'.$page, function (CacheItemInterface $item) use ($repo, $page) {
$item->expiresAfter(604800); // 1 week

return $this->fetchReleases('symfony', $repo, $page);
});
}

/**
* @return string
*
* @internal
*/
private function fetchPackageChangelog(string $owner, string $repo): string
{
// https://github.com/symfony/ux-twig-component/blob/2.x/CHANGELOG.md
// https://raw.githubusercontent.com/symfony/ux-twig-component/2.x/CHANGELOG.md
$response = $this->httpClient->request('GET', sprintf('https://raw.githubusercontent.com/%s/%s/2.x/CHANGELOG.md', $owner, $repo));

return $response->getContent();
}

/**
Expand Down
35 changes: 35 additions & 0 deletions ux.symfony.com/src/Service/Packagist/PackagistDataProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace App\Service\Packagist;

use Symfony\Contracts\Cache\CacheInterface;
use Symfony\Contracts\Cache\ItemInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;

class PackagistDataProvider
{
public function __construct(
private HttpClientInterface $httpClient,
private CacheInterface $cache,
)
{
}

public function getPackageData(string $packageName): array
{
return $this->cache->get('package-data-'.str_replace('/', '--', $packageName), function (ItemInterface $item) use ($packageName) {
$item->expiresAfter(604800); // 1 week

return $this->fetchPackageData($packageName);
});
}

private function fetchPackageData(string $packageName): array
{
$response = $this->httpClient->request('GET', 'https://packagist.org/packages/'.$packageName.'.json');

$packageData = $response->toArray();

return $packageData['package'] ?? [];
}
}
58 changes: 58 additions & 0 deletions ux.symfony.com/templates/ux_packages/package_changelog.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{% extends 'base.html.twig' %}

{% set meta = {
title: package.humanName,
description: package.description,
canonical: url(package.route),
} %}

{% block header %}
{{ include('_header.html.twig', {
theme: 'white'
}) }}
{% endblock %}

{% block content %}

<article>

{% block package_header %}
{{ block('package_header', 'ux_packages/%s.html.twig'|format(package.name|u.snake)) }}

<nav style="display: flex; align-items: center; justify-content: center; background: #0A0A0A; color:#fff; padding: 1rem; gap: 2rem;">
<a href="{{ url(package.route) }}" style="color:#fff;">{{ package.humanName }}</a>

<a href="{{ url('app_packageapp_package_requirements', {package: package.name}) }}" style="color:#fff;">Requirements</a>
<a href="{{ url('app_packageapp_package_changelog', {package: package.name}) }}" style="color:#fff;">Install</a>

<a href="{{ url('app_packageapp_package_changelog', {package: package.name}) }}" style="color:#fff;">Install</a>

<a href="{{ url('app_packageapp_package_changelog', {package: package.name}) }}" style="color:#fff;">Doc</a>
<a href="{{ url('app_packageapp_package_changelog', {package: package.name}) }}" style="color:#fff;">Demos</a>

<a href="{{ url('app_packageapp_package_changelog', {package: package.name}) }}" style="color:#fff;">Changelog</a>
<a href="{{ url('app_packageapp_package_changelog', {package: package.name}) }}" style="color:#fff;">Issue</a>
</nav>
{% endblock %}

{% block package_content %}

<div class="hero">
<div class="container-fluid container-xxl px-4 pt-4 px-md-5">
<h1 class="text-center mt-5"><a href="{{ url('app_changelog') }}">Changelog</a></h1>
<p class="text-center mt-2 mb-5">New features, bug fixes, performances and security improvements.</p>
</div>
</div>

<div class="container-fluid container-xxl px-4 pt-4 px-md-5">
<div class="Changelog">
{% for entry in changelog %}
<twig:ChangelogItem item="{{ entry }}" isOpen="{{ loop.index < 4 }}" />
{% endfor %}
</div>
</div>

{% endblock %}
</article>

{% endblock %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{% extends 'base.html.twig' %}

{% set meta = {
title: package.humanName,
description: package.description,
canonical: url(package.route),
} %}

{% block header %}
{{ include('_header.html.twig', {
theme: 'white'
}) }}
{% endblock %}

{% block content %}

<article>

{% block package_header %}
{{ block('package_header', 'ux_packages/%s.html.twig'|format(package.name|u.snake)) }}

<nav style="display: flex; align-items: center; justify-content: center; background: #0A0A0A; color:#fff; padding: 1rem; gap: 2rem;">
<a href="{{ url(package.route) }}" style="color:#fff;">{{ package.humanName }}</a>

<a href="{{ url('app_packageapp_package_requirements', {package: package.name}) }}" style="color:#fff;">Requirements</a>
<a href="{{ url('app_packageapp_package_changelog', {package: package.name}) }}" style="color:#fff;">Install</a>

<a href="{{ url('app_packageapp_package_changelog', {package: package.name}) }}" style="color:#fff;">Install</a>

<a href="{{ url('app_packageapp_package_changelog', {package: package.name}) }}" style="color:#fff;">Doc</a>
<a href="{{ url('app_packageapp_package_changelog', {package: package.name}) }}" style="color:#fff;">Demos</a>

<a href="{{ url('app_packageapp_package_changelog', {package: package.name}) }}" style="color:#fff;">Changelog</a>
<a href="{{ url('app_packageapp_package_changelog', {package: package.name}) }}" style="color:#fff;">Issue</a>
</nav>
{% endblock %}

{% block package_content %}

<div class="hero">
<div class="container-fluid container-xxl px-4 pt-4 px-md-5">
<h1 class="text-center mt-5"><a href="{{ url('app_changelog') }}">{{ package.name }} Requirements</a></h1>
<p class="text-center mt-2 mb-5">New features, bug fixes, performances and security improvements.</p>
</div>
</div>

<div class="container-fluid container-xxl px-4 pt-4 px-md-5">

{{ dump(requirements) }}
</div>

{% endblock %}
</article>

{% endblock %}

0 comments on commit 9bd4ca5

Please sign in to comment.