Add exact application files

This commit is contained in:
2026-01-21 02:10:12 +03:00
parent d25a8abc80
commit df33488ad7
7 changed files with 1586 additions and 0 deletions

230
public/index.php Normal file
View File

@@ -0,0 +1,230 @@
<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
use DI\Container;
require __DIR__ . '/../vendor/autoload.php';
session_start();
// DIконтейнер
$container = new Container();
AppFactory::setContainer($container);
$app = AppFactory::create();
// В dev включаем подробные ошибки (можно выключить в проде)
$app->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 (массовая вставка)
$app->post('/api/table/import-csv', 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'];
$rows = $payload['rows'] ?? [];
$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');
});
// 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();