- Add DISCOVERY_LOG_LEVEL=debug - Add DISCOVERY_SHOW_PROGRESS=true - Temporary changes for debugging InitializerProcessor fixes on production
226 lines
5.8 KiB
PHP
226 lines
5.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Framework\Console\Components;
|
|
|
|
use App\Framework\Console\ConsoleColor;
|
|
use App\Framework\Console\ConsoleFormat;
|
|
use App\Framework\Console\ConsoleOutput;
|
|
use App\Framework\Console\ConsoleStyle;
|
|
|
|
/**
|
|
* TreeHelper zum Anzeigen hierarchischer Baumstrukturen in der Konsole.
|
|
* Ähnlich dem Symfony TreeHelper, aber angepasst an unser Styling-System.
|
|
*/
|
|
final class TreeHelper
|
|
{
|
|
private string $prefix = '';
|
|
|
|
private bool $isLastElement = true;
|
|
|
|
private ?ConsoleStyle $nodeStyle = null;
|
|
|
|
private ?ConsoleStyle $leafStyle = null;
|
|
|
|
private ?ConsoleStyle $lineStyle = null;
|
|
|
|
/**
|
|
* @var array<array{title: string, node: ?self, isLeaf: bool}>
|
|
*/
|
|
private array $nodes = [];
|
|
|
|
public function __construct(
|
|
private string $title = '',
|
|
private ConsoleOutput $output = new ConsoleOutput(),
|
|
) {
|
|
$this->nodeStyle = ConsoleStyle::create(color: ConsoleColor::BRIGHT_YELLOW, format: ConsoleFormat::BOLD);
|
|
$this->leafStyle = ConsoleStyle::create(color: ConsoleColor::WHITE);
|
|
$this->lineStyle = ConsoleStyle::create(color: ConsoleColor::GRAY);
|
|
}
|
|
|
|
/**
|
|
* Setzt den Stil für Knotentitel (Verzeichnisse/Kategorien).
|
|
*/
|
|
public function setNodeStyle(?ConsoleStyle $style): self
|
|
{
|
|
$this->nodeStyle = $style;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Setzt den Stil für Blätter/Endpunkte.
|
|
*/
|
|
public function setLeafStyle(?ConsoleStyle $style): self
|
|
{
|
|
$this->leafStyle = $style;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Setzt den Stil für Baumlinien.
|
|
*/
|
|
public function setLineStyle(?ConsoleStyle $style): self
|
|
{
|
|
$this->lineStyle = $style;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Setzt den Haupttitel des Baums.
|
|
*/
|
|
public function setTitle(string $title): self
|
|
{
|
|
$this->title = $title;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Fügt einen Unterknoten (z.B. Unterverzeichnis) hinzu.
|
|
*/
|
|
public function addNode(string $title): self
|
|
{
|
|
$node = new self($title);
|
|
$node->nodeStyle = $this->nodeStyle;
|
|
$node->leafStyle = $this->leafStyle;
|
|
$node->lineStyle = $this->lineStyle;
|
|
|
|
$this->nodes[] = [
|
|
'title' => $title,
|
|
'node' => $node,
|
|
'isLeaf' => false,
|
|
];
|
|
|
|
return $node;
|
|
}
|
|
|
|
/**
|
|
* Fügt einen Endpunkt (z.B. Datei) hinzu.
|
|
*/
|
|
public function addLeaf(string $title): self
|
|
{
|
|
$this->nodes[] = [
|
|
'title' => $title,
|
|
'node' => null,
|
|
'isLeaf' => true,
|
|
];
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Zeigt die vollständige Baumstruktur an.
|
|
*/
|
|
public function display(): void
|
|
{
|
|
if (! empty($this->title)) {
|
|
$this->output->writeLine($this->title, $this->nodeStyle);
|
|
}
|
|
|
|
$this->displayTree();
|
|
}
|
|
|
|
/**
|
|
* Rendert die Baumstruktur und gibt den Text zurück.
|
|
*/
|
|
public function render(): string
|
|
{
|
|
$output = '';
|
|
|
|
if (! empty($this->title)) {
|
|
$output .= $this->nodeStyle->apply($this->title) . "\n";
|
|
}
|
|
|
|
$output .= $this->renderTree();
|
|
|
|
return $output;
|
|
}
|
|
|
|
/**
|
|
* Setzt den Präfix für die aktuelle Ebene.
|
|
* (Interne Methode für rekursives Rendern)
|
|
*/
|
|
private function setPrefix(string $prefix, bool $isLastElement): self
|
|
{
|
|
$this->prefix = $prefix;
|
|
$this->isLastElement = $isLastElement;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Zeigt die Baumstruktur mit dem aktuellen Präfix an.
|
|
* (Interne Methode für rekursives Rendern)
|
|
*/
|
|
private function displayTree(): void
|
|
{
|
|
$count = count($this->nodes);
|
|
|
|
foreach ($this->nodes as $index => $item) {
|
|
$isLast = ($index === $count - 1);
|
|
$nodePrefix = $this->prefix . ($this->isLastElement ? ' ' : '│ ');
|
|
|
|
// Baumlinien und Verbindungen
|
|
$connector = $isLast ? '└── ' : '├── ';
|
|
$linePrefix = $this->prefix . $connector;
|
|
|
|
// Titel anzeigen
|
|
$style = $item['isLeaf'] ? $this->leafStyle : $this->nodeStyle;
|
|
$title = $linePrefix . $item['title'];
|
|
|
|
$this->output->writeLine(
|
|
$this->lineStyle->apply($linePrefix) .
|
|
$style->apply($item['title'])
|
|
);
|
|
|
|
// Unterelemente rekursiv anzeigen
|
|
if (! $item['isLeaf'] && $item['node'] !== null) {
|
|
$item['node']
|
|
->setPrefix($nodePrefix, $isLast)
|
|
->displayTree();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Rendert die Baumstruktur mit dem aktuellen Präfix und gibt den Text zurück.
|
|
* (Interne Methode für rekursives Rendern)
|
|
*/
|
|
private function renderTree(): string
|
|
{
|
|
$output = '';
|
|
$count = count($this->nodes);
|
|
|
|
foreach ($this->nodes as $index => $item) {
|
|
$isLast = ($index === $count - 1);
|
|
$nodePrefix = $this->prefix . ($this->isLastElement ? ' ' : '│ ');
|
|
|
|
// Baumlinien und Verbindungen
|
|
$connector = $isLast ? '└── ' : '├── ';
|
|
$linePrefix = $this->prefix . $connector;
|
|
|
|
// Titel formatieren
|
|
$style = $item['isLeaf'] ? $this->leafStyle : $this->nodeStyle;
|
|
$title = $item['title'];
|
|
|
|
$output .= $this->lineStyle->apply($linePrefix) .
|
|
$style->apply($title) . "\n";
|
|
|
|
// Unterelemente rekursiv rendern
|
|
if (! $item['isLeaf'] && $item['node'] !== null) {
|
|
$childOutput = $item['node']
|
|
->setPrefix($nodePrefix, $isLast)
|
|
->renderTree();
|
|
|
|
$output .= $childOutput;
|
|
}
|
|
}
|
|
|
|
return $output;
|
|
}
|
|
}
|