<?php
declare(strict_types=1); use App\Routing\Router; use App\Http\Controllers\CardController; use App\Application\CardService; use App\Application\BinderService; use App\Storage\LocalFileSystem; use App\Http\Response; use App\Http\Controllers\BinderController; use App\Http\Controllers\FileController; use App\Http\Controllers\SettingsController; use App\Application\SettingsService; use App\Domain\Tags\TagNormalizer; return function(Router $router) { $storagePath = realpath(__DIR__ . '/../../storage') ?: __DIR__ . '/../../storage'; $fs = new LocalFileSystem($storagePath); $clock = new \App\Application\SystemClock(); $tagNormalizer = new TagNormalizer(); $service = new CardService($fs, $clock, $tagNormalizer); $binderService = new BinderService($fs, $clock); $extendedHosts = []; if ($fs->exists('meta/url_fetch_hosts.json')) { $decoded = json_decode($fs->read('meta/url_fetch_hosts.json'), true); if (is_array($decoded)) { foreach ($decoded as $host => $maxBytes) { if (is_string($host) && is_numeric($maxBytes)) { $extendedHosts[$host] = (int)$maxBytes; } } } } $httpClient = new \App\Infrastructure\CurlHttpClient(); $urlFetcher = new \App\Domain\UrlFetcher($httpClient, $extendedHosts); $controller = new CardController($service, $binderService, 'php://input', $urlFetcher, $storagePath); $binderController = new BinderController($binderService); $fileController = new FileController($service); $settingsService = new SettingsService($fs); $settingsController = new SettingsController($settingsService); $dispatch = function(callable $action) { return function(...$args) use ($action) { $result = $action(...$args); $status = $result['status'] ?? 200; $body = $result['body'] ?? []; Response::json($body, $status); }; }; $readRequestBody = function(): string { return file_get_contents('php://input'); }; $router->get('/api/ping', function() { Response::json(['message' => 'pong']); }); $router->get('/api/version', function() { $versionFile = dirname(__DIR__, 2) . '/VERSION'; $version = trim(file_get_contents($versionFile)); Response::json(['version' => $version]); }); $router->get('/api/cards', $dispatch([$controller, 'index'])); $router->get('/api/tags', $dispatch([$controller, 'getTags'])); $router->post('/api/cards', $dispatch([$controller, 'store'])); $router->post('/api/cards/url', $dispatch([$controller, 'storeUrl'])); $router->post('/api/cards/gc', $dispatch([$controller, 'gc'])); $router->post('/api/cards/reset-by-binder', $dispatch([$controller, 'resetByBinder'])); $router->patch('/api/cards/bulk-tags', $dispatch([$controller, 'bulkUpdateTags'])); $router->get('/api/cards/{id}', $dispatch([$controller, 'show'])); $router->put('/api/cards/{id}', $dispatch([$controller, 'update'])); $router->patch('/api/cards/{id}/status', $dispatch([$controller, 'updateStatus'])); $router->post('/api/cards/locations', $dispatch([$controller, 'getLocations'])); $router->post('/api/cards/image', $dispatch([$controller, 'storeImage'])); $router->delete('/api/cards/{id}', function($id) use ($controller, $dispatch) { $action = $dispatch([$controller, 'destroy']); $action($id); }); $router->get('/api/binderes', $dispatch([$binderController, 'index'])); $router->post('/api/binderes', function() use ($binderController, $dispatch, $readRequestBody) { $payload = $readRequestBody(); $action = $dispatch([$binderController, 'store']); $action($payload); }); $router->get('/api/binderes/{id}', function($id) use ($binderController, $dispatch) { $action = $dispatch([$binderController, 'show']); $action($id); }); $router->put('/api/binderes/{id}', function($id) use ($binderController, $dispatch, $readRequestBody) { $payload = $readRequestBody(); $action = $dispatch([$binderController, 'update']); $action($id, $payload); }); $router->put('/api/binderes/{id}/placements', function($id) use ($binderController, $dispatch, $readRequestBody) { $payload = $readRequestBody(); $action = $dispatch([$binderController, 'updatePlacements']); $action($id, $payload); }); $router->delete('/api/binderes/{id}', function($id) use ($binderController, $dispatch) { $action = $dispatch([$binderController, 'destroy']); $action($id); }); $router->get('/api/file/preview', function() use ($fileController, $dispatch) { $action = $dispatch([$fileController, 'preview']); $action(); }); $router->get('/api/file/text-preview', $dispatch([$fileController, 'textPreview'])); $router->post('/api/file/open-explorer', $dispatch([$fileController, 'openExplorer'])); $router->get('/api/settings', $dispatch([$settingsController, 'index'])); $router->put('/api/settings', $dispatch([$settingsController, 'update'])); }; 