fix: Gitea Traefik routing and connection pool optimization
Some checks failed
🚀 Build & Deploy Image / Determine Build Necessity (push) Failing after 10m14s
🚀 Build & Deploy Image / Build Runtime Base Image (push) Has been skipped
🚀 Build & Deploy Image / Build Docker Image (push) Has been skipped
🚀 Build & Deploy Image / Run Tests & Quality Checks (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Staging (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Production (push) Has been skipped
Security Vulnerability Scan / Check for Dependency Changes (push) Failing after 11m25s
Security Vulnerability Scan / Composer Security Audit (push) Has been cancelled

- Remove middleware reference from Gitea Traefik labels (caused routing issues)
- Optimize Gitea connection pool settings (MAX_IDLE_CONNS=30, authentication_timeout=180s)
- Add explicit service reference in Traefik labels
- Fix intermittent 504 timeouts by improving PostgreSQL connection handling

Fixes Gitea unreachability via git.michaelschiemer.de
This commit is contained in:
2025-11-09 14:46:15 +01:00
parent 85c369e846
commit 36ef2a1e2c
1366 changed files with 104925 additions and 28719 deletions

View File

@@ -0,0 +1,253 @@
<?php
declare(strict_types=1);
namespace App\Framework\Display\Formatters;
use App\Framework\Display\Formatters\CsvFormatter;
use App\Framework\Display\Formatters\JsonFormatter;
use App\Framework\Display\Formatters\XmlFormatter;
use App\Framework\Display\Formatters\YamlFormatter;
use App\Framework\Display\ValueObjects\DisplayOptions;
use App\Framework\Display\ValueObjects\OutputFormat;
use App\Framework\Filesystem\ValueObjects\FilePath;
/**
* Auto-detecting formatter that automatically selects the appropriate formatter
* based on the input data type.
*
* This is the main entry point for the Display module. It automatically detects
* the type of input data and routes it to the appropriate formatter:
* - Arrays → ArrayFormatter
* - Objects → ObjectFormatter
* - JSON strings → JsonFormatter
* - YAML strings → YamlFormatter
* - XML strings → XmlFormatter
* - CSV strings → CsvFormatter
* - Class names → ClassFormatter
* - Directory paths → FilesystemFormatter
* - Scalars → Scalar formatting
*
* @example
* $formatter = new AutoFormatter();
* echo $formatter->formatForConsole($data);
*/
final readonly class AutoFormatter
{
public function __construct(
private ArrayFormatter $arrayFormatter = new ArrayFormatter(),
private ObjectFormatter $objectFormatter = new ObjectFormatter(),
private ClassFormatter $classFormatter = new ClassFormatter(),
private FilesystemFormatter $filesystemFormatter = new FilesystemFormatter(),
private JsonFormatter $jsonFormatter = new JsonFormatter(),
private YamlFormatter $yamlFormatter = new YamlFormatter(),
private XmlFormatter $xmlFormatter = new XmlFormatter(),
private CsvFormatter $csvFormatter = new CsvFormatter(),
private CodeFormatter $codeFormatter = new CodeFormatter(),
) {
}
/**
* Format data with specified options and output format.
*
* @param mixed $value The data to format (array, object, string, etc.)
* @param DisplayOptions $options Display configuration options
* @param OutputFormat $format Output format (CONSOLE or HTML)
* @return string Formatted output string
*/
public function format(mixed $value, DisplayOptions $options, OutputFormat $format): string
{
return match (true) {
is_array($value) => $this->formatArray($value, $options, $format),
is_object($value) => $this->formatObject($value, $options, $format),
is_string($value) && $this->isJsonString($value) => $this->formatJsonString($value, $options, $format),
is_string($value) && $this->isYamlString($value) => $this->formatYamlString($value, $options, $format),
is_string($value) && $this->isXmlString($value) => $this->formatXmlString($value, $options, $format),
is_string($value) && $this->isCsvString($value) => $this->formatCsvString($value, $options, $format),
is_string($value) && CodeFormatter::isPhpCode($value) => $this->formatCode($value, $options, $format),
is_string($value) && class_exists($value) => $this->formatClass($value, $options, $format),
is_string($value) && (is_dir($value) || ($value instanceof FilePath && is_dir($value->toString()))) => $this->formatDirectory($value, $options, $format),
$value instanceof FilePath => $this->formatDirectory($value, $options, $format),
default => $this->formatScalar($value, $options, $format),
};
}
/**
* Format data for console output with default options.
*
* @param mixed $value The data to format
* @param DisplayOptions|null $options Optional display options (defaults to DisplayOptions::default())
* @return string Formatted console output with ANSI colors
*/
public function formatForConsole(mixed $value, ?DisplayOptions $options = null): string
{
$options ??= DisplayOptions::default();
return $this->format($value, $options, OutputFormat::CONSOLE);
}
/**
* Format data for HTML output with default options.
*
* @param mixed $value The data to format
* @param DisplayOptions|null $options Optional display options (defaults to DisplayOptions::default())
* @return string Formatted HTML output with semantic HTML/CSS classes
*/
public function formatForHtml(mixed $value, ?DisplayOptions $options = null): string
{
$options ??= DisplayOptions::default();
return $this->format($value, $options, OutputFormat::HTML);
}
private function formatArray(array $value, DisplayOptions $options, OutputFormat $format): string
{
// Check if array contains objects - could use ObjectFormatter for items
$hasObjects = false;
foreach ($value as $item) {
if (is_object($item)) {
$hasObjects = true;
break;
}
}
return $this->arrayFormatter->format($value, $options, $format);
}
private function formatObject(object $value, DisplayOptions $options, OutputFormat $format): string
{
return $this->objectFormatter->format($value, $options, $format);
}
private function formatJsonString(string $value, DisplayOptions $options, OutputFormat $format): string
{
return $this->jsonFormatter->format($value, $options, $format);
}
private function formatYamlString(string $value, DisplayOptions $options, OutputFormat $format): string
{
return $this->yamlFormatter->format($value, $options, $format);
}
private function formatXmlString(string $value, DisplayOptions $options, OutputFormat $format): string
{
return $this->xmlFormatter->format($value, $options, $format);
}
private function formatCsvString(string $value, DisplayOptions $options, OutputFormat $format): string
{
return $this->csvFormatter->format($value, $options, $format);
}
private function formatCode(string $value, DisplayOptions $options, OutputFormat $format): string
{
return $this->codeFormatter->format($value, $options, $format);
}
private function formatClass(string $className, DisplayOptions $options, OutputFormat $format): string
{
return $this->classFormatter->format($className, $options, $format);
}
private function formatDirectory(string|FilePath $path, DisplayOptions $options, OutputFormat $format): string
{
return $this->filesystemFormatter->format($path, $options, $format);
}
private function formatScalar(mixed $value, DisplayOptions $options, OutputFormat $format): string
{
$formatted = match (true) {
is_string($value) => $format === OutputFormat::HTML
? '<span class="display-string">' . htmlspecialchars($value) . '</span>'
: "\033[32m\"{$value}\"\033[0m",
is_int($value) => $format === OutputFormat::HTML
? '<span class="display-number">' . $value . '</span>'
: "\033[94m{$value}\033[0m",
is_float($value) => $format === OutputFormat::HTML
? '<span class="display-number">' . $value . '</span>'
: "\033[94m{$value}\033[0m",
is_bool($value) => $format === OutputFormat::HTML
? '<span class="display-boolean">' . ($value ? 'true' : 'false') . '</span>'
: "\033[95m" . ($value ? 'true' : 'false') . "\033[0m",
is_null($value) => $format === OutputFormat::HTML
? '<span class="display-null">null</span>'
: "\033[90mnull\033[0m",
default => $format === OutputFormat::HTML
? '<span class="display-type">' . htmlspecialchars(get_debug_type($value)) . '</span>'
: get_debug_type($value),
};
return $formatted;
}
private function isJsonString(string $value): bool
{
if (empty($value)) {
return false;
}
$trimmed = trim($value);
if (! ($trimmed[0] === '{' || $trimmed[0] === '[')) {
return false;
}
return json_validate($value);
}
private function isYamlString(string $value): bool
{
if (empty($value)) {
return false;
}
$trimmed = trim($value);
// Basic YAML detection: starts with key: or has --- or ...
// More sophisticated detection would require a YAML parser
return preg_match('/^(\s*[a-zA-Z_][a-zA-Z0-9_]*\s*:|\s*---|\s*\.\.\.)/', $trimmed) === 1;
}
private function isXmlString(string $value): bool
{
if (empty($value)) {
return false;
}
$trimmed = trim($value);
// Basic XML detection: starts with < or <?xml
return str_starts_with($trimmed, '<') || str_starts_with($trimmed, '<?xml');
}
private function isCsvString(string $value): bool
{
if (empty($value)) {
return false;
}
$lines = explode("\n", $value);
if (count($lines) < 2) {
return false;
}
// Check if the first line contains common CSV separators
$firstLine = $lines[0];
$separators = [',', ';', "\t"];
foreach ($separators as $separator) {
$parts = explode($separator, $firstLine);
if (count($parts) >= 2) {
// Check if second line has same number of parts
if (isset($lines[1])) {
$secondParts = explode($separator, $lines[1]);
if (count($secondParts) >= 2 && abs(count($parts) - count($secondParts)) <= 1) {
return true;
}
}
}
}
return false;
}
}