• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

cypht-org / cypht / 40343422939

26 Oct 2026 02:50PM UTC coverage: 81.555% (-5.5%) from 87.054%
40343422939

push

travis-ci

web-flow
Merge pull request #2100 from Shadow243/feat/web-based-configurations

feat(frontend/backend): reat/web based configurations

156 of 647 new or added lines in 5 files covered. (24.11%)

6040 of 7406 relevant lines covered (81.56%)

11.24 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/lib/database_setup.php
1
<?php
2

3
/**
4
 * Database schema setup and migrations, shared by scripts/setup_database.php
5
 * (CLI) and Hm_Installer (in-process). Throws instead of die()/exit() so a
6
 * failure here never kills the process it's called from.
7
 */
8

9
/**
10
 * Checks for required extensions based on the DB driver.
11
 */
12
function checkRequiredExtensions(string $db_driver) {
NEW
13
    $extensions = match ($db_driver) {
×
NEW
14
        'mysql' => ['mysqli', 'mysqlnd', 'pdo_mysql'],
×
NEW
15
        'pgsql' => ['pgsql', 'pdo_pgsql'],
×
NEW
16
        'sqlite' => [],
×
NEW
17
        default => [],
×
NEW
18
    };
×
19

NEW
20
    $missing_extensions = array_filter($extensions, fn($ext) => !extension_loaded($ext));
×
21

NEW
22
    if (!empty($missing_extensions)) {
×
NEW
23
        throw new RuntimeException('Missing required extensions: ' . implode(', ', $missing_extensions));
×
24
    }
25
}
26

27
/**
28
 * Connects to the database, retrying once a second up to $max_tries times.
29
 */
30
function connect_database_with_retry(Hm_Site_Config_File $config, int $max_tries = 10): PDO {
NEW
31
    $connection_tries = 0;
×
32

NEW
33
    while (true) {
×
NEW
34
        $connection_tries++;
×
NEW
35
        $conn = Hm_DB::connect($config);
×
36

NEW
37
        if ($conn !== false) {
×
NEW
38
            printf("Database connection successful ...\n");
×
NEW
39
            return $conn;
×
40
        }
41

NEW
42
        if ($connection_tries >= $max_tries) {
×
NEW
43
            throw new RuntimeException('Unable to connect to database');
×
44
        }
45

NEW
46
        printf("Attempting to connect to database ... ({$connection_tries}/{$max_tries})\n");
×
NEW
47
        sleep(1);
×
48
    }
49
}
50

51
/**
52
 * Checks required extensions, connects, and runs schema setup/migrations
53
 * for the database described by $config.
54
 */
55
function run_database_setup(Hm_Site_Config_File $config, string $migrations_path) {
NEW
56
    $db_driver = $config->get('db_driver');
×
NEW
57
    $schema_path = APP_PATH.'database/'.$db_driver.'_schema.sql';
×
58

NEW
59
    checkRequiredExtensions($db_driver);
×
NEW
60
    $conn = connect_database_with_retry($config);
×
NEW
61
    setupDatabase($conn, $schema_path, $migrations_path, $db_driver);
×
62
}
63

64
/**
65
 * Initializes the database and runs migrations.
66
 */
67
function setupDatabase(PDO $pdo, string $schemaFile, string $migrationDir, string $db_driver) {
NEW
68
    if (isDatabaseEmpty($pdo, $db_driver)) {
×
NEW
69
        echo "Database is empty. Initializing...\n";
×
NEW
70
        initializeDatabase($pdo, $schemaFile, $migrationDir, $db_driver);
×
71
    } else {
NEW
72
        echo "Database detected. Running migrations...\n";
×
NEW
73
        ensureMigrationsTable($pdo, $db_driver);
×
NEW
74
        runMigrations($pdo, $migrationDir, $db_driver);
×
75
    }
76
}
77

78
/**
79
 * Checks if the database is empty (no tables exist).
80
 */
81
function isDatabaseEmpty(PDO $pdo, string $db_driver): bool {
NEW
82
    $checkTablesSql = match ($db_driver) {
×
NEW
83
        'mysql' => "SHOW TABLES;",
×
NEW
84
        'pgsql' => "SELECT table_name FROM information_schema.tables WHERE table_schema='public';",
×
NEW
85
        'sqlite' => "SELECT name FROM sqlite_master WHERE type='table';",
×
NEW
86
        default => throw new Exception("Unsupported database driver: " . $db_driver),
×
NEW
87
    };
×
88

NEW
89
    $tables = $pdo->query($checkTablesSql)->fetchAll(PDO::FETCH_COLUMN);
×
90

NEW
91
    return empty($tables);
×
92
}
93

94
/**
95
 * Ensures the `migrations` table exists for existing databases.
96
 */
97
function ensureMigrationsTable(PDO $pdo, string $db_driver) {
98
    try {
NEW
99
        $pdo->query("SELECT 1 FROM migrations LIMIT 1");
×
NEW
100
    } catch (PDOException $e) {
×
NEW
101
        echo "Migrations table not found. Creating it...\n";
×
102

NEW
103
        $createTableSql = match ($db_driver) {
×
NEW
104
            'mysql' => "
×
105
                CREATE TABLE migrations (
106
                    id INT AUTO_INCREMENT PRIMARY KEY,
107
                    migration VARCHAR(255) NOT NULL,
108
                    batch INT NOT NULL,
109
                    applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
110
                );
NEW
111
            ",
×
NEW
112
            'pgsql' => "
×
113
                CREATE TABLE migrations (
114
                    id SERIAL PRIMARY KEY,
115
                    migration VARCHAR(255) NOT NULL,
116
                    batch INT NOT NULL,
117
                    applied_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
118
                );
NEW
119
            ",
×
NEW
120
            'sqlite' => "
×
121
                CREATE TABLE migrations (
122
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
123
                    migration TEXT NOT NULL,
124
                    batch INTEGER NOT NULL,
125
                    applied_at TEXT DEFAULT CURRENT_TIMESTAMP
126
                );
NEW
127
            ",
×
NEW
128
            default => throw new Exception("Unsupported database driver: " . $db_driver),
×
NEW
129
        };
×
130

NEW
131
        $pdo->exec($createTableSql);
×
NEW
132
        echo "Migrations table created.\n";
×
133
    }
134
}
135

136
/**
137
 * Initializes the database schema and populates migrations for new installations.
138
 */
139
function initializeDatabase(PDO $pdo, string $schemaFile, string $migrationDir, string $db_driver) {
NEW
140
    $schemaSql = file_get_contents($schemaFile);
×
NEW
141
    $pdo->exec($schemaSql);
×
NEW
142
    echo "Database schema initialized.\n";
×
143

NEW
144
    ensureMigrationsTable($pdo, $db_driver);
×
145

NEW
146
    $migrationFiles = glob($migrationDir .'/'.$db_driver.'/*.sql');
×
NEW
147
    $stmt = $pdo->prepare("INSERT INTO migrations (migration, batch) VALUES (:migration, :batch)");
×
NEW
148
    foreach ($migrationFiles as $file) {
×
NEW
149
        $stmt->execute([
×
NEW
150
            'migration' => basename($file),
×
NEW
151
            'batch' => 0, // Mark as pre-applied
×
NEW
152
        ]);
×
153
    }
154

NEW
155
    echo "Migrations table populated for new installation.\n";
×
156
}
157

158
/**
159
 * Executes pending migrations for existing databases.
160
 */
161
function runMigrations(PDO $pdo, string $migrationDir, string $db_driver) {
NEW
162
    echo "Running migrations...\n";
×
163

NEW
164
    $executed = $pdo->query("SELECT migration FROM migrations")->fetchAll(PDO::FETCH_COLUMN);
×
NEW
165
    $migrationFiles = glob($migrationDir .'/'.$db_driver.'/*.sql');
×
NEW
166
    $stmt = $pdo->prepare("INSERT INTO migrations (migration, batch) VALUES (:migration, :batch)");
×
167

NEW
168
    foreach ($migrationFiles as $file) {
×
NEW
169
        $migrationName = basename($file);
×
NEW
170
        if (in_array($migrationName, $executed)) {
×
NEW
171
            continue;
×
172
        }
173

174
        try {
NEW
175
            $sql = file_get_contents($file);
×
NEW
176
            $pdo->exec($sql);
×
177

NEW
178
            $stmt->execute([
×
NEW
179
                'migration' => $migrationName,
×
NEW
180
                'batch' => 1
×
NEW
181
            ]);
×
182

NEW
183
            echo "Migrated: $migrationName\n";
×
NEW
184
        } catch (PDOException $e) {
×
NEW
185
            throw new RuntimeException("Migration failed for $migrationName: " . $e->getMessage());
×
186
        }
187
    }
188

NEW
189
    echo "Migrations completed.\n";
×
190
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc