docs: consolidate documentation into organized structure

- Move 12 markdown files from root to docs/ subdirectories
- Organize documentation by category:
  • docs/troubleshooting/ (1 file)  - Technical troubleshooting guides
  • docs/deployment/      (4 files) - Deployment and security documentation
  • docs/guides/          (3 files) - Feature-specific guides
  • docs/planning/        (4 files) - Planning and improvement proposals

Root directory cleanup:
- Reduced from 16 to 4 markdown files in root
- Only essential project files remain:
  • CLAUDE.md (AI instructions)
  • README.md (Main project readme)
  • CLEANUP_PLAN.md (Current cleanup plan)
  • SRC_STRUCTURE_IMPROVEMENTS.md (Structure improvements)

This improves:
 Documentation discoverability
 Logical organization by purpose
 Clean root directory
 Better maintainability
This commit is contained in:
2025-10-05 11:05:04 +02:00
parent 887847dde6
commit 5050c7d73a
36686 changed files with 196456 additions and 12398919 deletions

View File

@@ -0,0 +1,117 @@
<?php
declare(strict_types=1);
namespace App\Application\Admin\Service;
use App\Application\Admin\ValueObjects\AdminLayoutData;
use App\Application\Admin\ValueObjects\Breadcrumb;
use App\Application\Admin\ValueObjects\BreadcrumbCollection;
use App\Application\Admin\ValueObjects\NavigationItem;
use App\Application\Admin\ValueObjects\NavigationMenu;
use App\Application\Admin\ValueObjects\NavigationSection;
use App\Framework\Http\HttpRequest;
final readonly class AdminLayoutProcessor
{
public function __construct(
private AdminNavigationService $navigationService,
private HttpRequest $request
) {
}
/**
* Helper method to process layout from array data (convenience method)
*/
public function processLayoutFromArray(array $data): array
{
$adminLayoutData = AdminLayoutData::fromArray([
'title' => $data['title'] ?? 'Admin',
'currentPath' => $this->request->getPath(),
]);
$processedLayoutData = $this->processAdminLayout($adminLayoutData);
return array_merge($processedLayoutData->toArray(), $data);
}
public function processAdminLayout(AdminLayoutData $layoutData): AdminLayoutData
{
$currentPath = $this->request->path;
try {
$menuData = $this->navigationService->getNavigationMenu();
$navigationMenu = $this->buildNavigationMenu($menuData, $currentPath);
} catch (\Exception $e) {
error_log("AdminLayoutProcessor: Failed to get navigation menu: " . $e->getMessage());
// Fallback to default menu structure
$navigationMenu = $this->createFallbackMenu();
}
try {
$breadcrumbsData = $this->navigationService->getBreadcrumbs($currentPath);
$breadcrumbs = $this->buildBreadcrumbs($breadcrumbsData, $currentPath);
} catch (\Exception $e) {
error_log("AdminLayoutProcessor: Failed to get breadcrumbs: " . $e->getMessage());
// Fallback breadcrumbs
$breadcrumbs = new BreadcrumbCollection([
new Breadcrumb('Admin', '/admin'),
]);
}
return $layoutData
->withNavigationMenu($navigationMenu)
->withBreadcrumbs($breadcrumbs);
}
private function buildNavigationMenu(array $menuData, string $currentPath): NavigationMenu
{
$sections = [];
foreach ($menuData as $sectionName => $sectionData) {
$items = [];
foreach ($sectionData['items'] as $name => $url) {
$items[] = new NavigationItem(
name: $name,
url: $url,
isActive: $url === $currentPath
);
}
$sections[] = new NavigationSection(
name: $sectionName,
items: $items,
icon: $sectionData['icon'] ?? null
);
}
return new NavigationMenu($sections);
}
private function createFallbackMenu(): NavigationMenu
{
$systemSection = new NavigationSection(
name: 'System',
items: [
new NavigationItem('Dashboard', '/admin'),
new NavigationItem('Health Check', '/admin/system/health'),
],
icon: 'server'
);
return new NavigationMenu([$systemSection]);
}
private function buildBreadcrumbs(array $breadcrumbsData, string $currentPath): BreadcrumbCollection
{
$breadcrumbs = [];
foreach ($breadcrumbsData as $breadcrumbData) {
$breadcrumbs[] = new Breadcrumb(
name: $breadcrumbData['name'],
url: $breadcrumbData['url'] ?? null,
isActive: ($breadcrumbData['url'] ?? null) === $currentPath
);
}
return new BreadcrumbCollection($breadcrumbs);
}
}

View File

@@ -0,0 +1,180 @@
<?php
declare(strict_types=1);
namespace App\Application\Admin\Service;
use App\Framework\Router\UrlGenerator;
final readonly class AdminNavigationService
{
public function __construct(
private UrlGenerator $urlGenerator
) {
}
public function getNavigationMenu(): array
{
error_log("AdminNavigationService: Starting navigation menu generation");
$menuDefinition = [
'System' => [
'icon' => 'server',
'routes' => [
'Dashboard' => 'admin.dashboard',
'Performance' => 'admin.system.performance',
'Environment' => 'admin.system.environment',
'Health Check' => 'admin.system.health',
'PHP Info' => 'admin.system.phpinfo',
],
],
'Infrastructure' => [
'icon' => 'database',
'routes' => [
'Redis' => 'admin.infrastructure.redis',
'Cache Metrics' => 'admin.infrastructure.cache',
'Services' => 'admin.infrastructure.services',
],
'static' => [
'Logs' => '/admin/infrastructure/logs', // TODO: Add named route
],
],
'Development' => [
'icon' => 'code',
'routes' => [
'Routes' => 'admin.dev.routes',
'Design System' => 'admin.dev.design-system',
'WAF Testing' => 'admin.dev.waf-test',
],
'static' => [
'Style Guide' => '/admin/dev/styleguide', // TODO: Add named route
],
],
'Analytics' => [
'icon' => 'chart-bar',
'routes' => [
'Dashboard' => 'admin.analytics.dashboard',
],
],
'Content' => [
'icon' => 'photo',
'routes' => [
'Image Manager' => 'admin.content.images',
'Image Slots' => 'admin.content.image-slots',
],
],
];
$menu = [];
foreach ($menuDefinition as $sectionName => $sectionData) {
error_log("AdminNavigationService: Processing section '{$sectionName}'");
$items = [];
// Process routes
if (isset($sectionData['routes'])) {
foreach ($sectionData['routes'] as $itemName => $routeName) {
try {
$items[$itemName] = $this->urlGenerator->route($routeName);
error_log("AdminNavigationService: Successfully generated route '{$routeName}' for '{$itemName}'");
} catch (\Exception $e) {
error_log("AdminNavigationService: Failed to generate route '{$routeName}' for '{$itemName}': " . $e->getMessage());
// Generate fallback URL from route name - better mapping
$fallbackUrl = match ($routeName) {
'admin.dashboard' => '/admin',
'admin.system.health' => '/admin/system/health',
'admin.system.phpinfo' => '/admin/system/phpinfo',
'admin.system.performance' => '/admin/system/performance',
'admin.system.environment' => '/admin/system/environment',
'admin.infrastructure.redis' => '/admin/infrastructure/redis',
'admin.infrastructure.cache' => '/admin/infrastructure/cache',
'admin.infrastructure.services' => '/admin/infrastructure/services',
'admin.dev.routes' => '/admin/dev/routes',
'admin.dev.design-system' => '/admin/dev/design-system',
'admin.dev.waf-test' => '/admin/dev/waf-test',
'admin.analytics.dashboard' => '/admin/analytics/dashboard',
'admin.content.images' => '/admin/content/images',
'admin.content.image-slots' => '/admin/content/image-slots',
default => '/' . str_replace('.', '/', $routeName)
};
$items[$itemName] = $fallbackUrl;
error_log("AdminNavigationService: Using fallback URL '{$fallbackUrl}' for '{$itemName}'");
}
}
}
// Add static routes
if (isset($sectionData['static'])) {
foreach ($sectionData['static'] as $itemName => $url) {
$items[$itemName] = $url;
error_log("AdminNavigationService: Added static route '{$url}' for '{$itemName}'");
}
}
$menu[$sectionName] = [
'icon' => $sectionData['icon'],
'items' => $items,
];
}
error_log("AdminNavigationService: Successfully completed navigation menu generation");
return $menu;
}
public function getCurrentSection(string $currentPath): ?string
{
$menu = $this->getNavigationMenu();
foreach ($menu as $section => $data) {
foreach ($data['items'] as $name => $url) {
if (str_starts_with($currentPath, $url)) {
return $section;
}
}
}
return null;
}
public function getBreadcrumbs(string $currentPath): array
{
$menu = $this->getNavigationMenu();
$breadcrumbs = [
['name' => 'Admin', 'url' => $this->urlGenerator->route('admin.dashboard')],
];
foreach ($menu as $section => $data) {
foreach ($data['items'] as $name => $url) {
if ($currentPath === $url || str_starts_with($currentPath, $url)) {
if ($url !== $this->urlGenerator->route('admin.dashboard')) {
$breadcrumbs[] = ['name' => $section, 'url' => null];
$breadcrumbs[] = ['name' => $name, 'url' => $url];
}
return $breadcrumbs;
}
}
}
return $breadcrumbs;
}
public function getActiveMenuItem(string $currentPath): ?string
{
$menu = $this->getNavigationMenu();
foreach ($menu as $section => $data) {
foreach ($data['items'] as $name => $url) {
if ($currentPath === $url || str_starts_with($currentPath, $url)) {
return $name;
}
}
}
return null;
}
}