diff --git a/db/config.php b/db/config.php
index 7644cf3..4e0f57c 100644
--- a/db/config.php
+++ b/db/config.php
@@ -1,8 +1,14 @@
$settings['DB_HOST'],
+ 'DB_PORT' => $settings['DB_PORT'],
+ 'DB_NAME' => $settings['DB_NAME'],
+ 'DB_USER' => $settings['DB_USER'],
+ 'DB_PASS' => $settings['DB_PASS'],
+ ], true) . ";
+";
+
+ return $payload;
+}
+
+function db_read_settings_file(string $path): array
+{
+ static $cache = [];
+
+ if (array_key_exists($path, $cache)) {
+ return $cache[$path];
+ }
+
+ $result = [
+ 'settings' => db_normalize_settings([]),
+ 'error' => null,
+ ];
+
+ if (!is_file($path)) {
+ $cache[$path] = $result;
+ return $result;
+ }
+
+ try {
+ $loaded = include $path;
+ } catch (Throwable $exception) {
+ $result['error'] = $exception->getMessage();
+ $cache[$path] = $result;
+ return $result;
+ }
+
+ if (!is_array($loaded)) {
+ $result['error'] = 'Format file konfigurasi harus return array.';
+ $cache[$path] = $result;
+ return $result;
+ }
+
+ $result['settings'] = db_normalize_settings($loaded);
+ $cache[$path] = $result;
+
+ return $result;
+}
+
function db_env_settings(): array
{
$settings = [];
@@ -34,23 +110,24 @@ function db_env_settings(): array
return db_normalize_settings($settings);
}
-function db_local_settings(): array
+function db_manual_settings(): array
{
- static $settings = null;
+ return db_read_settings_file(DB_MANUAL_CONFIG_FILE)['settings'];
+}
- if (is_array($settings)) {
- return $settings;
- }
+function db_manual_settings_error(): ?string
+{
+ return db_read_settings_file(DB_MANUAL_CONFIG_FILE)['error'];
+}
- if (!is_file(DB_INSTALLER_CONFIG_FILE)) {
- $settings = db_normalize_settings([]);
- return $settings;
- }
+function db_legacy_installer_settings(): array
+{
+ return db_read_settings_file(DB_INSTALLER_CONFIG_FILE)['settings'];
+}
- $loaded = include DB_INSTALLER_CONFIG_FILE;
- $settings = is_array($loaded) ? db_normalize_settings($loaded) : db_normalize_settings([]);
-
- return $settings;
+function db_legacy_installer_settings_error(): ?string
+{
+ return db_read_settings_file(DB_INSTALLER_CONFIG_FILE)['error'];
}
function db_settings_complete(array $settings): bool
@@ -68,33 +145,24 @@ function db_resolved_settings(): array
return $settings;
}
- $env = db_env_settings();
- $local = db_local_settings();
- $envComplete = db_settings_complete($env);
- $localComplete = db_settings_complete($local);
-
- if ($envComplete && $localComplete) {
- $error = null;
- if (db_test_connection($env, true, $error)) {
- $env['__source'] = 'env';
- $settings = $env;
- return $settings;
- }
-
- $local['__source'] = 'file';
- $settings = $local;
+ $manual = db_manual_settings();
+ if (db_settings_complete($manual)) {
+ $manual['__source'] = 'manual_file';
+ $settings = $manual;
return $settings;
}
- if ($envComplete) {
+ $env = db_env_settings();
+ if (db_settings_complete($env)) {
$env['__source'] = 'env';
$settings = $env;
return $settings;
}
- if ($localComplete) {
- $local['__source'] = 'file';
- $settings = $local;
+ $legacy = db_legacy_installer_settings();
+ if (db_settings_complete($legacy)) {
+ $legacy['__source'] = 'legacy_installer_file';
+ $settings = $legacy;
return $settings;
}
@@ -117,6 +185,21 @@ function db_config_source(): string
return db_resolved_settings()['__source'] ?? 'missing';
}
+function db_configuration_problem(): ?string
+{
+ $manualError = db_manual_settings_error();
+ if ($manualError !== null) {
+ return 'Ada error di file ' . db_manual_config_relative_path() . ': ' . $manualError;
+ }
+
+ $legacyError = db_legacy_installer_settings_error();
+ if ($legacyError !== null) {
+ return 'Ada error di file lama db/installer-config.php: ' . $legacyError;
+ }
+
+ return null;
+}
+
function db_has_required_config(): bool
{
return db_settings_complete(db_resolved_settings());
@@ -185,7 +268,7 @@ function db(): PDO
}
if (!db_has_required_config()) {
- throw new RuntimeException('Database belum dikonfigurasi.');
+ throw new RuntimeException('Database belum dikonfigurasi. Isi file ' . db_manual_config_relative_path() . '.');
}
$pdo = db_create_pdo(db_resolved_settings(), true);
@@ -226,21 +309,9 @@ function db_create_database_if_missing(array $settings): void
function db_save_local_settings(array $settings): void
{
$settings = db_normalize_settings($settings);
- $payload = " $settings['DB_HOST'],
- 'DB_PORT' => $settings['DB_PORT'],
- 'DB_NAME' => $settings['DB_NAME'],
- 'DB_USER' => $settings['DB_USER'],
- 'DB_PASS' => $settings['DB_PASS'],
- ], true) . ";
-";
-
- $bytes = file_put_contents(DB_INSTALLER_CONFIG_FILE, $payload, LOCK_EX);
+ $bytes = file_put_contents(DB_MANUAL_CONFIG_FILE, $payload, LOCK_EX);
if ($bytes === false) {
throw new RuntimeException('Gagal menyimpan file konfigurasi database. Pastikan folder db bisa ditulis.');
}
diff --git a/db/database.php b/db/database.php
new file mode 100644
index 0000000..032b42e
--- /dev/null
+++ b/db/database.php
@@ -0,0 +1,16 @@
+ 'localhost',
+ 'DB_PORT' => '3306',
+ 'DB_NAME' => '',
+ 'DB_USER' => '',
+ 'DB_PASS' => '',
+];
diff --git a/healthz.php b/healthz.php
index fe27cdb..34d11bc 100644
--- a/healthz.php
+++ b/healthz.php
@@ -13,7 +13,10 @@ if (empty($status['ready'])) {
'php_version' => PHP_VERSION,
'time_utc' => gmdate('c'),
'db' => 'setup_required',
+ 'source' => $status['source'] ?? 'missing',
+ 'config_path' => db_manual_config_relative_path(),
'message' => $status['message'],
+ 'details' => $status['details'],
], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
exit;
}
@@ -29,6 +32,7 @@ try {
'time_utc' => gmdate('c'),
'posts' => $count,
'db' => 'ok',
+ 'source' => $status['source'] ?? 'unknown',
], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
} catch (Throwable $exception) {
http_response_code(503);
diff --git a/includes/site.php b/includes/site.php
index 47f1bfb..9485a33 100644
--- a/includes/site.php
+++ b/includes/site.php
@@ -156,7 +156,7 @@ function site_installation_status(): array
if (!db_has_required_config()) {
$status['message'] = 'Koneksi database belum diatur.';
- $status['details'] = 'Masukkan host, port, nama database, username, dan password di installer.';
+ $status['details'] = db_configuration_problem() ?: ('Isi host, port, nama database, username, dan password di file ' . db_manual_config_relative_path() . '.');
return $status;
}
@@ -173,6 +173,169 @@ function site_installation_status(): array
return $status;
}
+function render_manual_database_setup_screen(array $status): void
+{
+ $configPath = db_manual_config_relative_path();
+ $exampleConfig = db_export_settings_file([
+ 'DB_HOST' => 'localhost',
+ 'DB_PORT' => '3306',
+ 'DB_NAME' => 'usernamecpanel_namadb',
+ 'DB_USER' => 'usernamecpanel_userdb',
+ 'DB_PASS' => 'password_database',
+ ]);
+
+ http_response_code(503);
+ header('Content-Type: text/html; charset=utf-8');
+ ?>
+
+
+
+
+
+ = e(project_name()) ?> - Setup Database Manual
+
+
+
+
+
+
+
+ Setup manual
+ Isi file = e($configPath) ?> dulu.
+ Installer form sudah tidak dipakai. Sekarang koneksi database diisi manual lewat file PHP supaya lebih aman dan lebih cocok untuk cPanel/shared hosting.
+
+
+
= e((string)$status['message']) ?>
+
+
= e((string)$status['details']) ?>
+
+
+
+
+
+ Langkah cepat
+
+ - Buka file
= e($configPath) ?> di hosting atau editor.
+ - Isi
DB_HOST, DB_PORT, DB_NAME, DB_USER, dan DB_PASS.
+ - Kalau database belum ada, buat dulu di cPanel lalu import
db/database.sql.
+ - Reload halaman ini setelah file disimpan.
+
+
+
+ Contoh isi file
+ = e($exampleConfig) ?>
+
+
+
+
+
+
+
+
+ 'environment server',
- 'file' => 'file installer lokal',
- default => 'belum ada',
- };
+ switch ($source) {
+ case 'manual_file':
+ return 'file manual db/database.php';
+ case 'env':
+ return 'environment server';
+ case 'legacy_installer_file':
+ return 'file legacy db/installer-config.php';
+ default:
+ return 'belum ada';
+ }
}
$status = site_installation_status();
-$nextPath = safe_install_next_path((string)($_REQUEST['next'] ?? '/'));
-$formData = [
- 'db_host' => DB_HOST !== '' ? DB_HOST : 'localhost',
- 'db_port' => DB_PORT !== '' ? DB_PORT : '3306',
- 'db_name' => DB_NAME,
- 'db_user' => DB_USER,
- 'db_pass' => DB_PASS,
-];
-$errors = [];
-$flash = null;
-
-if (($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'POST') {
- $formData = [
- 'db_host' => trim((string)($_POST['db_host'] ?? 'localhost')),
- 'db_port' => trim((string)($_POST['db_port'] ?? '3306')),
- 'db_name' => trim((string)($_POST['db_name'] ?? '')),
- 'db_user' => trim((string)($_POST['db_user'] ?? '')),
- 'db_pass' => (string)($_POST['db_pass'] ?? ''),
- ];
- $nextPath = safe_install_next_path((string)($_POST['next'] ?? '/'));
-
- if ($formData['db_host'] === '') {
- $formData['db_host'] = 'localhost';
- }
- if ($formData['db_port'] === '') {
- $formData['db_port'] = '3306';
- }
-
- if ($formData['db_name'] === '') {
- $errors['db_name'] = 'Nama database wajib diisi.';
- }
- if ($formData['db_user'] === '') {
- $errors['db_user'] = 'Username database wajib diisi.';
- }
- if (!ctype_digit($formData['db_port']) || (int)$formData['db_port'] < 1 || (int)$formData['db_port'] > 65535) {
- $errors['db_port'] = 'Port harus berupa angka 1 sampai 65535.';
- }
-
- if ($errors === []) {
- $settings = [
- 'DB_HOST' => $formData['db_host'],
- 'DB_PORT' => $formData['db_port'],
- 'DB_NAME' => $formData['db_name'],
- 'DB_USER' => $formData['db_user'],
- 'DB_PASS' => $formData['db_pass'],
- ];
-
- try {
- $connectionError = db_connection_error($settings);
- if ($connectionError !== null && db_error_is_missing_database($connectionError)) {
- db_create_database_if_missing($settings);
- $connectionError = db_connection_error($settings);
- }
-
- if ($connectionError !== null) {
- throw new RuntimeException($connectionError);
- }
-
- db_save_local_settings($settings);
- header('Location: ' . $nextPath);
- exit;
- } catch (Throwable $exception) {
- $flash = [
- 'type' => 'danger',
- 'title' => 'Koneksi database gagal.',
- 'message' => $exception->getMessage(),
- ];
- }
- } else {
- $flash = [
- 'type' => 'warning',
- 'title' => 'Form belum lengkap.',
- 'message' => 'Periksa lagi field yang diberi tanda merah.',
- ];
- }
-}
+$nextPath = safe_install_next_path((string)($_GET['next'] ?? '/'));
+$configPath = db_manual_config_relative_path();
+$configTemplate = db_export_settings_file([
+ 'DB_HOST' => 'localhost',
+ 'DB_PORT' => '3306',
+ 'DB_NAME' => 'usernamecpanel_namadb',
+ 'DB_USER' => 'usernamecpanel_userdb',
+ 'DB_PASS' => 'password_database',
+]);
render_page_start([
- 'title' => 'Installer Database',
- 'description' => 'Form instalasi cepat untuk menghubungkan aplikasi ke database MySQL.',
+ 'title' => 'Konfigurasi Database Manual',
+ 'description' => 'Panduan isi file db/database.php untuk koneksi MySQL atau MariaDB.',
'canonical' => canonical_for('install.php'),
'robots' => 'noindex,nofollow',
- 'keywords' => 'installer database, setup mysql, setup php app',
+ 'keywords' => 'konfigurasi database manual, mysql cpanel, database php',
'body_class' => 'install-page',
]);
?>
@@ -105,20 +43,19 @@ render_page_start([
-
Auto installer
-
Pindah hosting? Tinggal isi data database, lalu website jalan lagi.
-
Kalau script ini dipindah ke server baru, halaman ini akan muncul otomatis saat koneksi database belum siap. Anda hanya perlu memasukkan host, port, nama database, username, dan password MySQL.
+
Setup manual
+
Installer form dinonaktifkan. Isi database lewat file PHP saja.
+
Sekarang koneksi MySQL/MariaDB memakai file = e($configPath) ?>. Jadi saat pindah ke cPanel/shared hosting, Anda cukup edit satu file lalu reload website.
Yang perlu disiapkan
- - Host database, seringnya
localhost.
+ - Host database, biasanya
localhost.
- Port MySQL, default
3306.
- - Nama database dari hosting/cPanel.
+ - Nama database dari cPanel atau hosting.
- Username dan password database.
-
Jika database yang Anda tulis belum ada, installer akan mencoba membuatnya otomatis jika akun database punya izin.
@@ -130,8 +67,8 @@ render_page_start([
Status saat ini
Aplikasi sudah terhubung ke database.
- Sumber konfigurasi aktif: = e(installer_source_label((string)$status['source'])) ?>.
- Kalau Anda hanya ingin memakai website, tidak perlu mengisi ulang form di kanan.
+ Sumber konfigurasi aktif: = e(manual_source_label((string)$status['source'])) ?>.
+ Kalau website sudah normal, file = e($configPath) ?> tidak perlu diubah lagi.
= e((string)$status['message']) ?>
@@ -139,72 +76,51 @@ render_page_start([
= e((string)$status['details']) ?>
- Begitu data database benar, aplikasi akan membuat tabel blog otomatis saat Anda masuk ke halaman utama.
+ Setelah file manual terisi benar, website akan membuat tabel blog otomatis saat halaman utama dibuka.
-
-
-
Form koneksi
-
Isi data MySQL / MariaDB
-
Data ini biasanya ada di menu Database pada panel hosting atau PHPMyAdmin.
-
-
Apa itu PHPMyAdmin?
+
+
File yang diedit
+
Buka = e($configPath) ?> lalu isi seperti ini
+
Anda tidak perlu submit form. Cukup simpan file, lalu refresh browser.
-
-
-
= e((string)$flash['title']) ?>
-
= e((string)$flash['message']) ?>
-
-
+
= e($configTemplate) ?>
-
-
-
Masuk ke website
-
Ke beranda
+
+ Untuk cPanel, nama database dan username sering wajib memakai prefix akun. Contoh: jika akun cPanel kawaii, maka bisa menjadi kawaii_appdb dan kawaii_appuser.
+
+
+
+
+
+
Urutan setup
+
+ - Buat database MySQL di cPanel.
+ - Import
db/database.sql lewat phpMyAdmin.
+ - Edit file
= e($configPath) ?>.
+ - Buka ulang halaman website.
+
+
-
-
diff --git a/robots.txt b/robots.txt
index 95ce749..bda6f05 100644
--- a/robots.txt
+++ b/robots.txt
@@ -1,4 +1,4 @@
User-agent: *
Allow: /
Disallow: /admin.php
-Sitemap: https://baclink-apknusa-microsite-ad42.dev.flatlogic.app/sitemap.xml
+Sitemap: http://127.0.0.1/sitemap.xml
diff --git a/sitemap.xml b/sitemap.xml
index a5dd743..1972cd8 100644
--- a/sitemap.xml
+++ b/sitemap.xml
@@ -1,49 +1,49 @@
- https://baclink-apknusa-microsite-ad42.dev.flatlogic.app/
- 2026-05-17T14:40:34+00:00
+ http://127.0.0.1/
+ 2026-05-17T16:04:30+00:00
daily
1.0
- https://baclink-apknusa-microsite-ad42.dev.flatlogic.app/blog.php
- 2026-05-17T14:40:34+00:00
+ http://127.0.0.1/blog.php
+ 2026-05-17T16:04:30+00:00
daily
0.8
- https://baclink-apknusa-microsite-ad42.dev.flatlogic.app/post.php?slug=checklist-link-seo-ke-apknusa-com
+ http://127.0.0.1/post.php?slug=checklist-link-seo-ke-apknusa-com
2026-05-17T13:29:20+00:00
weekly
0.7
- https://baclink-apknusa-microsite-ad42.dev.flatlogic.app/post.php?slug=perbedaan-apk-xapk-dan-file-instalasi-lain-yang-perlu-dipahami
+ http://127.0.0.1/post.php?slug=perbedaan-apk-xapk-dan-file-instalasi-lain-yang-perlu-dipahami
2026-05-17T13:29:11+00:00
weekly
0.7
- https://baclink-apknusa-microsite-ad42.dev.flatlogic.app/post.php?slug=tips-menyimpan-file-apk-supaya-mudah-dicari-lagi
+ http://127.0.0.1/post.php?slug=tips-menyimpan-file-apk-supaya-mudah-dicari-lagi
2026-05-17T13:29:11+00:00
weekly
0.7
- https://baclink-apknusa-microsite-ad42.dev.flatlogic.app/post.php?slug=kenapa-review-aplikasi-penting-sebelum-download
+ http://127.0.0.1/post.php?slug=kenapa-review-aplikasi-penting-sebelum-download
2026-05-17T13:29:11+00:00
weekly
0.7
- https://baclink-apknusa-microsite-ad42.dev.flatlogic.app/post.php?slug=panduan-update-aplikasi-android-tanpa-kehilangan-data
+ http://127.0.0.1/post.php?slug=panduan-update-aplikasi-android-tanpa-kehilangan-data
2026-05-17T13:29:11+00:00
weekly
0.7
- https://baclink-apknusa-microsite-ad42.dev.flatlogic.app/post.php?slug=cara-memilih-sumber-apk-yang-aman-sebelum-instal
+ http://127.0.0.1/post.php?slug=cara-memilih-sumber-apk-yang-aman-sebelum-instal
2026-05-17T13:29:11+00:00
weekly
0.7