Files
Felix KemmlerandClaude Sonnet 5 b6c1389c55 Reorganize into monorepo layout, move mitarbeiter-app to legacy reference
Consolidates the previously separate omsorgapp and omsorgCore repos
(each had their own nested .git with GitHub history) plus the old
root-level website/mitarbeiter-app into a single monorepo, matching
the structure already documented in the root CLAUDE.md. Also moves
the PHP employee app aside as omsorgWeb/mitarbeiter-app-legacy/ to
serve as a template for a ground-up rewrite.

Fixes .gitignore in the same pass: the config-secrets/uploads/data
patterns were unanchored (relative to repo root, not depth-agnostic),
so they silently stopped matching once the app moved under omsorgWeb/.
Patterns are now **/-prefixed and cover both mitarbeiter-app and
mitarbeiter-app-legacy, keeping DB/SMTP credentials and uploaded
employee documents out of version control.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-07 14:21:37 +02:00

91 lines
3.0 KiB
PHP

<?php
function db(): PDO {
static $pdo = null;
if ($pdo === null) {
$c = require __DIR__ . '/config.php';
$pdo = new PDO(
$c['db_dsn'],
$c['db_user'],
$c['db_password'],
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]
);
if ($c['db_driver'] === 'sqlite') {
$pdo->exec('PRAGMA journal_mode=WAL; PRAGMA foreign_keys=ON;');
}
_run_migrations($pdo);
}
return $pdo;
}
function _table_exists(PDO $pdo, string $table, string $driver): bool {
if ($driver === 'sqlite') {
return (bool) $pdo->query(
"SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name=" . $pdo->quote($table)
)->fetchColumn();
}
return (bool) $pdo->query(
"SELECT COUNT(*) FROM information_schema.tables WHERE table_schema=DATABASE() AND table_name=" . $pdo->quote($table)
)->fetchColumn();
}
function _run_migrations(PDO $pdo): void {
$c = require __DIR__ . '/config.php';
$driver = $c['db_driver'];
$migrationTableExisted = _table_exists($pdo, 'schema_migrations', $driver);
$pdo->exec("
CREATE TABLE IF NOT EXISTS schema_migrations (
version VARCHAR(255) NOT NULL PRIMARY KEY,
applied_at VARCHAR(32) NOT NULL
)
");
$files = glob(__DIR__ . '/../migrations/*.php');
if (!$files) return;
sort($files);
// Existing DB without migration table: stamp all known migrations as applied.
if (!$migrationTableExisted && _table_exists($pdo, 'users', $driver)) {
$insertIgnore = $driver === 'sqlite' ? 'INSERT OR IGNORE' : 'INSERT IGNORE';
$stmt = $pdo->prepare(
"$insertIgnore INTO schema_migrations (version, applied_at) VALUES (?, ?)"
);
foreach ($files as $file) {
$stmt->execute([basename($file, '.php'), date('c')]);
}
return;
}
$applied = $pdo->query('SELECT version FROM schema_migrations')
->fetchAll(PDO::FETCH_COLUMN);
$applied = array_flip($applied);
$useTransactions = ($driver === 'sqlite');
foreach ($files as $file) {
$version = basename($file, '.php');
if (isset($applied[$version])) continue;
$migration = require $file;
if ($useTransactions) $pdo->beginTransaction();
try {
foreach ((array) $migration['up'] as $sql) {
$pdo->exec($sql);
}
$pdo->prepare(
'INSERT INTO schema_migrations (version, applied_at) VALUES (?, ?)'
)->execute([$version, date('c')]);
if ($useTransactions) $pdo->commit();
} catch (Throwable $e) {
if ($useTransactions && $pdo->inTransaction()) $pdo->rollBack();
throw new RuntimeException(
"Migration {$version} failed: " . $e->getMessage(), 0, $e
);
}
}
}