<?php
|
|
|
|
namespace App\Controller;
|
|
|
|
use App\Entity\Project;
|
|
use App\Service\TaskLifecycleManager;
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
use Symfony\Component\HttpFoundation\StreamedResponse;
|
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|
use Symfony\Component\Routing\Attribute\Route;
|
|
|
|
#[Route('/badge')]
|
|
class BadgeController extends AbstractController
|
|
{
|
|
#[Route('/project-status/{projectSlug}/{status}', name: 'app_badge_project_status')]
|
|
public function index(EntityManagerInterface $entityManager, TaskLifecycleManager $taskLifecycleManager, string $projectSlug, string $status): Response
|
|
{
|
|
$project = $entityManager->getRepository(Project::class)->findOneBySlug($projectSlug);
|
|
if (!$project) {
|
|
throw new NotFoundHttpException('Project not found');
|
|
}
|
|
|
|
$stats = $taskLifecycleManager->getProjectStats($project);
|
|
if (!isset($stats[$status])) {
|
|
throw new NotFoundHttpException('Status not found');
|
|
}
|
|
|
|
$stats = $stats[$status];
|
|
|
|
$response = new StreamedResponse();
|
|
|
|
$response->headers->set('Content-Type', 'image/svg+xml');
|
|
$response->headers->set('Cache-Control', 'public, max-age=300');
|
|
|
|
$response->setCallback(function () use ($stats): void {
|
|
$colors = [
|
|
'primary' => '#0d6efd', // $blue;
|
|
'secondary' => '#6c757d', // $gray-600;
|
|
'success' => '#198754', // $green;
|
|
'info' => '#0dcaf0', // $cyan;
|
|
'warning' => '#ffc107', // $yellow;
|
|
'danger' => '#dc3545', // $red;
|
|
];
|
|
|
|
$xml = new \DOMDocument();
|
|
|
|
$left = $stats['title'];
|
|
$leftColor = $colors['secondary'];
|
|
$right = sprintf(' % 3.0f%%', $stats['percentage']);
|
|
$rightColor = $colors[$stats['color']];
|
|
|
|
$charWidth = 7;
|
|
$fontSize = 11;
|
|
$totalHeight = 20;
|
|
$radius = ceil($totalHeight / $charWidth);
|
|
$verticalMargin = round(($totalHeight - $fontSize) / 2);
|
|
$horizontalMargin = round($fontSize / 3);
|
|
$totalWidth = round(strlen($left.$right) * $charWidth + 2 * $horizontalMargin);
|
|
$middle = floor(strlen($left) * $charWidth);
|
|
|
|
$svg = $xml->createElement('svg');
|
|
$svg->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns', 'http://www.w3.org/2000/svg');
|
|
$svg->setAttribute('width', $totalWidth);
|
|
$svg->setAttribute('height', $totalHeight);
|
|
|
|
$defs = $xml->createElement('defs');
|
|
|
|
$gradientId = 'a';
|
|
$gradient = $xml->createElement('linearGradient');
|
|
$gradient->setAttribute('id', $gradientId);
|
|
|
|
$stop = $xml->createElement('stop');
|
|
$stop->setAttribute('offset', ($middle * 100 / $totalWidth).'%');
|
|
$stop->setAttribute('stop-color', $leftColor);
|
|
$gradient->appendChild($stop);
|
|
|
|
$stop = $xml->createElement('stop');
|
|
$stop->setAttribute('offset', ($middle * 100 / $totalWidth).'%');
|
|
$stop->setAttribute('stop-color', $rightColor);
|
|
$gradient->appendChild($stop);
|
|
|
|
$defs->appendChild($gradient);
|
|
|
|
$svg->appendChild($defs);
|
|
|
|
$rect = $xml->createElement('rect');
|
|
$rect->setAttribute('width', $totalWidth);
|
|
$rect->setAttribute('height', $totalHeight);
|
|
$rect->setAttribute('rx', $radius);
|
|
$rect->setAttribute('style', sprintf('fill:url(#%s)', $gradientId));
|
|
|
|
$svg->appendChild($rect);
|
|
|
|
$fontG = $xml->createElement('g');
|
|
$fontG->setAttribute('font-family', implode(',', ['DejaVu Sans', 'Verdana', 'Geneva', 'sans-serif']));
|
|
$fontG->setAttribute('font-size', $fontSize);
|
|
|
|
$leftText = $xml->createElement('text', $left);
|
|
$leftText->setAttribute('x', $horizontalMargin);
|
|
$leftText->setAttribute('y', $totalHeight - $verticalMargin);
|
|
$leftText->setAttribute('fill', '#000');
|
|
$fontG->appendChild($leftText);
|
|
|
|
$leftText = $xml->createElement('text', $left);
|
|
$leftText->setAttribute('x', $horizontalMargin);
|
|
$leftText->setAttribute('y', $totalHeight - $verticalMargin - 1);
|
|
$leftText->setAttribute('fill', '#fff');
|
|
$fontG->appendChild($leftText);
|
|
|
|
$rightText = $xml->createElement('text', $right);
|
|
$rightText->setAttribute('x', $totalWidth - $horizontalMargin);
|
|
$rightText->setAttribute('y', $totalHeight - $verticalMargin);
|
|
$rightText->setAttribute('style', 'text-anchor:end;fill:#000');
|
|
$fontG->appendChild($rightText);
|
|
|
|
$rightText = $xml->createElement('text', $right);
|
|
$rightText->setAttribute('x', $totalWidth - $horizontalMargin);
|
|
$rightText->setAttribute('y', $totalHeight - $verticalMargin - 1);
|
|
$rightText->setAttribute('style', 'text-anchor:end;fill:#fff');
|
|
$fontG->appendChild($rightText);
|
|
|
|
$svg->appendChild($fontG);
|
|
|
|
$xml->appendChild($svg);
|
|
|
|
echo $xml->saveXML();
|
|
});
|
|
|
|
return $response;
|
|
}
|
|
}
|