chore: complete update

This commit is contained in:
2025-07-17 16:24:20 +02:00
parent 899227b0a4
commit 64a7051137
1300 changed files with 85570 additions and 2756 deletions

View File

@@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace App\Framework\Sitemap;
use DateTimeImmutable;
final readonly class SitemapEntry
{
public function __construct(
public string $url,
public DateTimeImmutable $lastmod,
public string $changefreq = 'monthly',
public float $priority = 0.5
) {}
public function toXml(): string
{
return sprintf(
'<url><loc>%s</loc><lastmod>%s</lastmod><changefreq>%s</changefreq><priority>%.1f</priority></url>',
htmlspecialchars($this->url),
$this->lastmod->format('Y-m-d'),
$this->changefreq,
$this->priority
);
}
}

View File

@@ -0,0 +1,100 @@
<?php
declare(strict_types=1);
namespace App\Framework\Sitemap;
use App\Framework\Attributes\Singleton;
use App\Framework\Core\Route;
use App\Framework\Http\Method;
use App\Framework\Router\RouteCollection;
use App\Framework\Router\UrlGenerator;
use Generator;
#[Singleton]
final readonly class SitemapGenerator
{
public function __construct(
private RouteCollection $routes,
private UrlGenerator $urlGenerator
) {}
/**
* Generiert Sitemap-URLs aus allen verfügbaren Named Routes
*
* @return Generator<SitemapEntry>
*/
public function generateFromRoutes(): Generator
{
foreach ($this->getPublicRoutes() as $route) {
if ($this->isStaticRoute($route)) {
yield new SitemapEntry(
url: $this->urlGenerator->absoluteRoute($route->name),
lastmod: new \DateTimeImmutable(),
changefreq: $this->determineChangeFreq($route),
priority: $this->determinePriority($route)
);
}
}
}
/**
* Holt alle öffentlichen Named Routes
*/
private function getPublicRoutes(): Generator
{
// Hier müssen Sie eine Methode in RouteCollection hinzufügen
foreach ($this->routes->getAllNamedRoutes() as $name => $route) {
// Nur GET-Routen für Sitemap: Named Routes sind aktuell immer nur Routes mit GET Methode
if (/*$this->supportsMethod($route, Method::GET) &&*/
!$this->isExcludedFromSitemap($route)) {
yield $route;
}
}
}
private function isStaticRoute(Route $route): bool
{
// Prüft ob Route keine Parameter benötigt
return !str_contains($route->path, '{');
}
private function supportsMethod(Route $route, Method $method): bool
{
return in_array($method->value, $route->method->value ?? [], true);
}
private function isExcludedFromSitemap(Route $route): bool
{
// Admin/API-Routen ausschließen
$excludePatterns = ['/admin', '/api', '/auth'];
foreach ($excludePatterns as $pattern) {
if (str_starts_with($route->path, $pattern)) {
return true;
}
}
return false;
}
private function determineChangeFreq(Route $route): string
{
// Basierend auf Route-Name oder Pfad
return match (true) {
str_contains($route->path, '/blog') => 'weekly',
str_contains($route->path, '/news') => 'daily',
$route->name === 'home' => 'weekly',
default => 'monthly'
};
}
private function determinePriority(Route $route): float
{
return match ($route->name) {
'home' => 1.0,
'about', 'contact' => 0.8,
default => 0.5
};
}
}