addErrorMiddleware(true, true, true); $container->set('db', function () { return \App\Db::connectFromSession(); }); // --- ROUTES --- // Статическая страница с фронтендом $app->get('/', function (Request $request, Response $response) { // Очень простой view встроен прямо здесь $html = file_get_contents(__DIR__ . '/index.html'); // вынесем в отдельный файл ниже $response->getBody()->write($html); return $response; }); // Логин: сохраняет логин/пароль MariaDB в сессии после проверки $app->post('/api/login', function (Request $request, Response $response) { $data = json_decode((string)$request->getBody(), true); $user = $data['user'] ?? ''; $pass = $data['pass'] ?? ''; try { \App\Db::testConnection($user, $pass); $_SESSION['db_user'] = $user; $_SESSION['db_pass'] = $pass; $payload = ['ok' => true]; $status = 200; } catch (\RuntimeException $e) { $payload = ['ok' => false, 'error' => $e->getMessage()]; $status = 401; } $response->getBody()->write(json_encode($payload)); return $response->withHeader('Content-Type', 'application/json') ->withStatus($status); }); // Middleware на /api/*: проверяем, что аутентифицированы $app->add(function (Request $request, $handler) { $path = $request->getUri()->getPath(); if (str_starts_with($path, '/api/') && $path !== '/api/login') { if (empty($_SESSION['db_user']) || empty($_SESSION['db_pass'])) { $res = new \Slim\Psr7\Response(); $res->getBody()->write(json_encode(['error' => 'Not authenticated'])); return $res->withStatus(401)->withHeader('Content-Type', 'application/json'); } } return $handler->handle($request); }); // API: дерево схем/таблиц $app->get('/api/tree', function (Request $request, Response $response) use ($container) { $pdo = $container->get('db'); $meta = new \App\MetaService($pdo); $tree = $meta->getSchemaTree(); $response->getBody()->write(json_encode($tree)); return $response->withHeader('Content-Type', 'application/json'); }); // API: метаданные таблицы $app->get('/api/table/meta', function (Request $request, Response $response) use ($container) { $params = $request->getQueryParams(); $schema = $params['schema'] ?? ''; $table = $params['table'] ?? ''; $pdo = $container->get('db'); $meta = new \App\MetaService($pdo); $data = $meta->getTableMeta($schema, $table); $response->getBody()->write(json_encode($data)); return $response->withHeader('Content-Type', 'application/json'); }); // API: данные таблицы $app->post('/api/table/data', function (Request $request, Response $response) use ($container) { $payload = json_decode((string)$request->getBody(), true); $schema = $payload['schema'] ?? ''; $table = $payload['table'] ?? ''; $page = (int)($payload['page'] ?? 1); $pageSize = (int)($payload['pageSize'] ?? 50); $filters = $payload['filters'] ?? []; $sort = $payload['sort'] ?? null; $columns = $payload['columns'] ?? []; // ✅ Логирование для отладки error_log("Data request: page=$page, pageSize=$pageSize, filters=" . json_encode($filters)); $pdo = $container->get('db'); $ds = new \App\DataService($pdo); $resData = $ds->fetchData($schema, $table, $columns, $page, $pageSize, $filters, $sort); // ✅ Логирование ответа error_log("Data response: " . json_encode([ 'data_count' => count($resData['data']), 'last_page' => $resData['last_page'], 'current_page' => $resData['current_page'], 'total' => $resData['total'] ])); $response->getBody()->write(json_encode($resData)); return $response->withHeader('Content-Type', 'application/json'); }); // API: insert / update / delete $app->post('/api/table/insert', function (Request $request, Response $response) use ($container) { $payload = json_decode((string)$request->getBody(), true); $pdo = $container->get('db'); $meta = new \App\MetaService($pdo); $ds = new \App\DataService($pdo); $schema = $payload['schema']; $table = $payload['table']; $row = $payload['row']; $metaArr = $meta->getTableMeta($schema, $table); $result = $ds->insertRow($schema, $table, $row, $metaArr['columns']); $response->getBody()->write(json_encode($result)); return $response->withHeader('Content-Type', 'application/json'); }); $app->post('/api/table/update', function (Request $request, Response $response) use ($container) { $payload = json_decode((string)$request->getBody(), true); $pdo = $container->get('db'); $meta = new \App\MetaService($pdo); $ds = new \App\DataService($pdo); $schema = $payload['schema']; $table = $payload['table']; $row = $payload['row']; $metaArr = $meta->getTableMeta($schema, $table); $result = $ds->updateRow($schema, $table, $row, $metaArr['columns'], $metaArr['primaryKey']); $response->getBody()->write(json_encode($result)); return $response->withHeader('Content-Type', 'application/json'); }); $app->post('/api/table/delete', function (Request $request, Response $response) use ($container) { $payload = json_decode((string)$request->getBody(), true); $pdo = $container->get('db'); $meta = new \App\MetaService($pdo); $ds = new \App\DataService($pdo); $schema = $payload['schema']; $table = $payload['table']; $row = $payload['row']; $metaArr = $meta->getTableMeta($schema, $table); $result = $ds->deleteRow($schema, $table, $row, $metaArr['primaryKey']); $response->getBody()->write(json_encode($result)); return $response->withHeader('Content-Type', 'application/json'); }); // API: импорт CSV (массовая вставка) // API: импорт CSV (массовая вставка) $app->post('/api/table/import-csv', function (Request $request, Response $response) use ($container) { $body = (string)$request->getBody(); $payload = json_decode($body, true); if (json_last_error() !== JSON_ERROR_NONE) { error_log("CSV Import: Invalid JSON - " . json_last_error_msg()); $response->getBody()->write(json_encode(['error' => 'Invalid JSON: ' . json_last_error_msg()])); return $response->withHeader('Content-Type', 'application/json')->withStatus(400); } $pdo = $container->get('db'); $meta = new \App\MetaService($pdo); $ds = new \App\DataService($pdo); $schema = $payload['schema'] ?? ''; $table = $payload['table'] ?? ''; $rows = $payload['rows'] ?? []; if (empty($schema) || empty($table)) { error_log("CSV Import: Missing schema or table"); $response->getBody()->write(json_encode(['error' => 'Schema and table are required'])); return $response->withHeader('Content-Type', 'application/json')->withStatus(400); } try { $metaArr = $meta->getTableMeta($schema, $table); $result = $ds->insertMultipleRows($schema, $table, $rows, $metaArr['columns']); $response->getBody()->write(json_encode($result)); return $response->withHeader('Content-Type', 'application/json'); } catch (\Exception $e) { error_log("CSV Import: Critical error - " . $e->getMessage()); $response->getBody()->write(json_encode([ 'error' => $e->getMessage(), 'inserted' => 0, 'errors' => 1 ])); return $response->withHeader('Content-Type', 'application/json')->withStatus(500); } }); // API: экспорт CSV $app->post('/api/table/export-csv', function (Request $request, Response $response) use ($container) { $payload = json_decode((string)$request->getBody(), true); $pdo = $container->get('db'); $ds = new \App\DataService($pdo); $schema = $payload['schema'] ?? ''; $table = $payload['table'] ?? ''; $filters = $payload['filters'] ?? []; $sort = $payload['sort'] ?? null; $columns = $payload['columns'] ?? []; $result = $ds->exportCSV($schema, $table, $columns, $filters, $sort); $response->getBody()->write(json_encode($result)); return $response->withHeader('Content-Type', 'application/json'); }); // API: получить доступные значения для Foreign Key $app->get('/api/fk-values', function (Request $request, Response $response) use ($container) { $params = $request->getQueryParams(); $schema = $params['schema'] ?? ''; $table = $params['table'] ?? ''; $column = $params['column'] ?? ''; $pdo = $container->get('db'); // Получаем до 100 первых значений $sql = "SELECT DISTINCT `{$column}` FROM `{$schema}`.`{$table}` WHERE `{$column}` IS NOT NULL ORDER BY `{$column}` LIMIT 100"; $stmt = $pdo->prepare($sql); $stmt->execute(); $values = $stmt->fetchAll(PDO::FETCH_COLUMN); $response->getBody()->write(json_encode(['values' => $values])); return $response->withHeader('Content-Type', 'application/json'); }); $app->run();