2026-03-04 20:46:11 +00:00
|
|
|
<?php
|
|
|
|
|
$pageTitle = 'Installer';
|
|
|
|
|
$step = (int)($step ?? 1);
|
|
|
|
|
$values = is_array($values ?? null) ? $values : [];
|
|
|
|
|
$smtpResult = is_array($smtp_result ?? null) ? $smtp_result : [];
|
|
|
|
|
$checks = is_array($checks ?? null) ? $checks : [];
|
|
|
|
|
|
|
|
|
|
$val = static function (string $key, string $default = '') use ($values): string {
|
|
|
|
|
return (string)($values[$key] ?? $default);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
ob_start();
|
|
|
|
|
?>
|
2026-03-04 22:00:53 +00:00
|
|
|
<style>
|
|
|
|
|
.ac-installer { max-width: 980px; margin: 0 auto; }
|
|
|
|
|
.ac-installer-title { margin: 16px 0 6px; font-size: 42px; line-height: 1.05; }
|
|
|
|
|
.ac-installer-intro { margin: 0; color: rgba(235,241,255,.75); }
|
|
|
|
|
.ac-installer-steps { display: flex; gap: 10px; margin-top: 18px; flex-wrap: wrap; }
|
|
|
|
|
.ac-step-pill {
|
|
|
|
|
padding: 8px 12px;
|
|
|
|
|
border-radius: 999px;
|
|
|
|
|
border: 1px solid rgba(255,255,255,.16);
|
|
|
|
|
background: rgba(255,255,255,.03);
|
|
|
|
|
font-size: 11px;
|
|
|
|
|
letter-spacing: .18em;
|
|
|
|
|
text-transform: uppercase;
|
|
|
|
|
font-family: 'IBM Plex Mono', monospace;
|
|
|
|
|
}
|
|
|
|
|
.ac-step-pill.is-active { background: rgba(57,244,179,.18); }
|
|
|
|
|
|
|
|
|
|
.ac-installer-form { margin-top: 18px; display: grid; gap: 14px; }
|
|
|
|
|
.ac-installer-grid {
|
|
|
|
|
display: grid;
|
|
|
|
|
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
|
|
|
|
gap: 12px;
|
|
|
|
|
}
|
|
|
|
|
.ac-installer-section {
|
|
|
|
|
margin-top: 6px;
|
|
|
|
|
padding-top: 14px;
|
|
|
|
|
border-top: 1px solid rgba(255,255,255,.10);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.ac-installer label {
|
|
|
|
|
display: inline-block;
|
|
|
|
|
margin: 0 0 8px;
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
color: rgba(238,244,255,.78);
|
|
|
|
|
text-transform: uppercase;
|
|
|
|
|
letter-spacing: .16em;
|
|
|
|
|
font-family: 'IBM Plex Mono', monospace;
|
|
|
|
|
}
|
|
|
|
|
.ac-installer .input,
|
|
|
|
|
.ac-installer textarea.input,
|
|
|
|
|
.ac-installer select.input {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 46px;
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
border: 1px solid rgba(255,255,255,.16);
|
|
|
|
|
background: rgba(12,16,24,.58);
|
|
|
|
|
color: #edf2ff;
|
|
|
|
|
padding: 0 14px;
|
|
|
|
|
font-size: 15px;
|
|
|
|
|
outline: none;
|
|
|
|
|
}
|
|
|
|
|
.ac-installer textarea.input {
|
|
|
|
|
height: auto;
|
|
|
|
|
min-height: 92px;
|
|
|
|
|
padding: 12px 14px;
|
|
|
|
|
resize: vertical;
|
|
|
|
|
}
|
|
|
|
|
.ac-installer .input:focus {
|
|
|
|
|
border-color: rgba(57,244,179,.55);
|
|
|
|
|
box-shadow: 0 0 0 3px rgba(57,244,179,.14);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.ac-installer-actions {
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: flex-end;
|
|
|
|
|
gap: 10px;
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
margin-top: 6px;
|
|
|
|
|
}
|
|
|
|
|
.ac-installer .button {
|
|
|
|
|
height: 44px;
|
|
|
|
|
border-radius: 999px;
|
|
|
|
|
padding: 0 18px;
|
|
|
|
|
border: 1px solid rgba(255,255,255,.2);
|
|
|
|
|
background: rgba(255,255,255,.04);
|
|
|
|
|
color: #eef4ff;
|
|
|
|
|
text-transform: uppercase;
|
|
|
|
|
letter-spacing: .16em;
|
|
|
|
|
font-family: 'IBM Plex Mono', monospace;
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
}
|
|
|
|
|
.ac-installer .button:hover { background: rgba(255,255,255,.1); }
|
|
|
|
|
.ac-installer .button-primary {
|
|
|
|
|
background: linear-gradient(135deg, #25afff, #2bd8ff);
|
|
|
|
|
border-color: rgba(40,185,255,.75);
|
|
|
|
|
color: #041019;
|
|
|
|
|
}
|
|
|
|
|
.ac-installer .button-primary:hover { filter: brightness(1.05); }
|
|
|
|
|
|
|
|
|
|
.ac-installer-alert {
|
|
|
|
|
margin-top: 16px;
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
padding: 12px 14px;
|
|
|
|
|
}
|
|
|
|
|
.ac-installer-alert.error {
|
|
|
|
|
border: 1px solid rgba(255,124,124,.45);
|
|
|
|
|
background: rgba(180,40,40,.18);
|
|
|
|
|
color: #ffd6d6;
|
|
|
|
|
}
|
|
|
|
|
.ac-installer-alert.success {
|
|
|
|
|
border: 1px solid rgba(57,244,179,.45);
|
|
|
|
|
background: rgba(10,90,60,.22);
|
|
|
|
|
color: #b8ffe5;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.ac-installer-checks {
|
|
|
|
|
padding: 12px;
|
|
|
|
|
border: 1px solid rgba(255,255,255,.1);
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
background: rgba(255,255,255,.02);
|
|
|
|
|
}
|
|
|
|
|
.ac-installer-checks-title {
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
text-transform: uppercase;
|
|
|
|
|
letter-spacing: .16em;
|
|
|
|
|
color: rgba(255,255,255,.65);
|
|
|
|
|
margin-bottom: 10px;
|
|
|
|
|
font-family: 'IBM Plex Mono', monospace;
|
|
|
|
|
}
|
|
|
|
|
</style>
|
|
|
|
|
|
|
|
|
|
<section class="card ac-installer">
|
2026-03-04 20:46:11 +00:00
|
|
|
<div class="badge">Setup</div>
|
2026-03-04 22:00:53 +00:00
|
|
|
<h1 class="ac-installer-title">AudioCore V1.5 Installer</h1>
|
|
|
|
|
<p class="ac-installer-intro">Deploy a fresh instance with validated SMTP and baseline health checks.</p>
|
|
|
|
|
|
|
|
|
|
<div class="ac-installer-steps">
|
|
|
|
|
<div class="ac-step-pill <?= $step === 1 ? 'is-active' : '' ?>">1. Core Setup</div>
|
|
|
|
|
<div class="ac-step-pill <?= $step === 2 ? 'is-active' : '' ?>">2. Site + SMTP</div>
|
2026-03-04 20:46:11 +00:00
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<?php if (!empty($error)): ?>
|
2026-03-04 22:00:53 +00:00
|
|
|
<div class="ac-installer-alert error"><?= htmlspecialchars((string)$error, ENT_QUOTES, 'UTF-8') ?></div>
|
2026-03-04 20:46:11 +00:00
|
|
|
<?php endif; ?>
|
|
|
|
|
<?php if (!empty($success)): ?>
|
2026-03-04 22:00:53 +00:00
|
|
|
<div class="ac-installer-alert success"><?= htmlspecialchars((string)$success, ENT_QUOTES, 'UTF-8') ?></div>
|
2026-03-04 20:46:11 +00:00
|
|
|
<?php endif; ?>
|
|
|
|
|
|
|
|
|
|
<?php if ($step === 1): ?>
|
2026-03-04 22:00:53 +00:00
|
|
|
<form method="post" action="/admin/install" class="ac-installer-form">
|
2026-03-04 20:46:11 +00:00
|
|
|
<input type="hidden" name="installer_action" value="setup_core">
|
2026-03-04 22:00:53 +00:00
|
|
|
<div class="ac-installer-grid">
|
2026-03-04 20:46:11 +00:00
|
|
|
<div>
|
|
|
|
|
<label>DB Host *</label>
|
|
|
|
|
<input class="input" name="db_host" value="<?= htmlspecialchars($val('db_host', 'localhost'), ENT_QUOTES, 'UTF-8') ?>">
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<label>DB Port *</label>
|
|
|
|
|
<input class="input" name="db_port" value="<?= htmlspecialchars($val('db_port', '3306'), ENT_QUOTES, 'UTF-8') ?>">
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<label>DB Name *</label>
|
|
|
|
|
<input class="input" name="db_name" value="<?= htmlspecialchars($val('db_name', ''), ENT_QUOTES, 'UTF-8') ?>">
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<label>DB User *</label>
|
|
|
|
|
<input class="input" name="db_user" value="<?= htmlspecialchars($val('db_user', ''), ENT_QUOTES, 'UTF-8') ?>">
|
|
|
|
|
</div>
|
|
|
|
|
<div style="grid-column:1/-1;">
|
|
|
|
|
<label>DB Password</label>
|
|
|
|
|
<input class="input" type="password" name="db_pass" value="">
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
2026-03-04 22:00:53 +00:00
|
|
|
<div class="ac-installer-section ac-installer-grid">
|
2026-03-04 20:46:11 +00:00
|
|
|
<div>
|
|
|
|
|
<label>Admin Name *</label>
|
|
|
|
|
<input class="input" name="admin_name" value="<?= htmlspecialchars($val('admin_name', 'Admin'), ENT_QUOTES, 'UTF-8') ?>">
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<label>Admin Email *</label>
|
|
|
|
|
<input class="input" type="email" name="admin_email" value="<?= htmlspecialchars($val('admin_email', ''), ENT_QUOTES, 'UTF-8') ?>">
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<label>Admin Password *</label>
|
|
|
|
|
<input class="input" type="password" name="admin_password" value="" placeholder="Minimum 8 characters">
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
2026-03-04 22:00:53 +00:00
|
|
|
<div class="ac-installer-actions">
|
2026-03-04 20:46:11 +00:00
|
|
|
<button type="submit" class="button button-primary">Create Core Setup</button>
|
|
|
|
|
</div>
|
|
|
|
|
</form>
|
|
|
|
|
<?php else: ?>
|
2026-03-04 22:00:53 +00:00
|
|
|
<form method="post" action="/admin/install" class="ac-installer-form">
|
|
|
|
|
<div class="ac-installer-grid">
|
2026-03-04 20:46:11 +00:00
|
|
|
<div>
|
|
|
|
|
<label>Site Title *</label>
|
|
|
|
|
<input class="input" name="site_title" value="<?= htmlspecialchars($val('site_title', 'AudioCore V1.5'), ENT_QUOTES, 'UTF-8') ?>">
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<label>Site Tagline</label>
|
|
|
|
|
<input class="input" name="site_tagline" value="<?= htmlspecialchars($val('site_tagline', 'Core CMS for DJs & Producers'), ENT_QUOTES, 'UTF-8') ?>">
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<label>SEO Title Suffix</label>
|
|
|
|
|
<input class="input" name="seo_title_suffix" value="<?= htmlspecialchars($val('seo_title_suffix', 'AudioCore V1.5'), ENT_QUOTES, 'UTF-8') ?>">
|
|
|
|
|
</div>
|
|
|
|
|
<div style="grid-column:1/-1;">
|
|
|
|
|
<label>SEO Meta Description</label>
|
2026-03-04 22:00:53 +00:00
|
|
|
<textarea class="input" name="seo_meta_description" rows="3"><?= htmlspecialchars($val('seo_meta_description', ''), ENT_QUOTES, 'UTF-8') ?></textarea>
|
2026-03-04 20:46:11 +00:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
2026-03-04 22:00:53 +00:00
|
|
|
<div class="ac-installer-section ac-installer-grid">
|
2026-03-04 20:46:11 +00:00
|
|
|
<div>
|
|
|
|
|
<label>SMTP Host *</label>
|
|
|
|
|
<input class="input" name="smtp_host" value="<?= htmlspecialchars($val('smtp_host', ''), ENT_QUOTES, 'UTF-8') ?>" placeholder="smtp.example.com">
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<label>SMTP Port *</label>
|
|
|
|
|
<input class="input" name="smtp_port" value="<?= htmlspecialchars($val('smtp_port', '587'), ENT_QUOTES, 'UTF-8') ?>">
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<label>SMTP User</label>
|
|
|
|
|
<input class="input" name="smtp_user" value="<?= htmlspecialchars($val('smtp_user', ''), ENT_QUOTES, 'UTF-8') ?>">
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<label>SMTP Password</label>
|
|
|
|
|
<input class="input" type="password" name="smtp_pass" value="<?= htmlspecialchars($val('smtp_pass', ''), ENT_QUOTES, 'UTF-8') ?>">
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<label>SMTP Encryption</label>
|
|
|
|
|
<input class="input" name="smtp_encryption" value="<?= htmlspecialchars($val('smtp_encryption', 'tls'), ENT_QUOTES, 'UTF-8') ?>" placeholder="tls or ssl">
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<label>SMTP From Email *</label>
|
|
|
|
|
<input class="input" type="email" name="smtp_from_email" value="<?= htmlspecialchars($val('smtp_from_email', ''), ENT_QUOTES, 'UTF-8') ?>">
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<label>SMTP From Name</label>
|
|
|
|
|
<input class="input" name="smtp_from_name" value="<?= htmlspecialchars($val('smtp_from_name', 'AudioCore V1.5'), ENT_QUOTES, 'UTF-8') ?>">
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<label>Test Recipient Email *</label>
|
|
|
|
|
<input class="input" type="email" name="smtp_test_email" value="<?= htmlspecialchars($val('smtp_test_email', ''), ENT_QUOTES, 'UTF-8') ?>">
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<?php if (!empty($smtpResult)): ?>
|
2026-03-04 22:00:53 +00:00
|
|
|
<div class="ac-installer-alert <?= !empty($smtpResult['ok']) ? 'success' : 'error' ?>" style="margin-top:0;">
|
|
|
|
|
<div style="font-weight:700; margin-bottom:4px;">
|
2026-03-04 20:46:11 +00:00
|
|
|
<?= !empty($smtpResult['ok']) ? 'SMTP test passed' : 'SMTP test failed' ?>
|
|
|
|
|
</div>
|
2026-03-04 22:00:53 +00:00
|
|
|
<div><?= htmlspecialchars((string)($smtpResult['message'] ?? ''), ENT_QUOTES, 'UTF-8') ?></div>
|
2026-03-04 20:46:11 +00:00
|
|
|
<?php if (!empty($smtpResult['debug'])): ?>
|
|
|
|
|
<details style="margin-top:8px;">
|
|
|
|
|
<summary style="cursor:pointer;">Debug output</summary>
|
|
|
|
|
<pre style="white-space:pre-wrap; margin-top:8px; font-size:12px; color:#cfd6f5;"><?= htmlspecialchars((string)$smtpResult['debug'], ENT_QUOTES, 'UTF-8') ?></pre>
|
|
|
|
|
</details>
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
</div>
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
|
|
|
|
|
<?php if (!empty($checks)): ?>
|
2026-03-04 22:00:53 +00:00
|
|
|
<div class="ac-installer-checks">
|
|
|
|
|
<div class="ac-installer-checks-title">Installer Health Checks</div>
|
2026-03-04 20:46:11 +00:00
|
|
|
<div style="display:grid; gap:8px;">
|
|
|
|
|
<?php foreach ($checks as $check): ?>
|
|
|
|
|
<div style="display:flex; gap:10px; align-items:flex-start;">
|
|
|
|
|
<span style="display:inline-flex; align-items:center; justify-content:center; width:18px; height:18px; border-radius:999px; font-size:12px; margin-top:2px; background:<?= !empty($check['ok']) ? 'rgba(57,244,179,.2)' : 'rgba(255,124,124,.2)' ?>; color:<?= !empty($check['ok']) ? '#9ff8d8' : '#ffb7b7' ?>;">
|
2026-03-04 22:00:53 +00:00
|
|
|
<?= !empty($check['ok']) ? '✓' : '!' ?>
|
2026-03-04 20:46:11 +00:00
|
|
|
</span>
|
|
|
|
|
<div>
|
|
|
|
|
<div style="font-weight:600;"><?= htmlspecialchars((string)($check['label'] ?? ''), ENT_QUOTES, 'UTF-8') ?></div>
|
|
|
|
|
<div style="color:rgba(235,241,255,.65); font-size:13px;"><?= htmlspecialchars((string)($check['detail'] ?? ''), ENT_QUOTES, 'UTF-8') ?></div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<?php endforeach; ?>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
|
2026-03-04 22:00:53 +00:00
|
|
|
<div class="ac-installer-actions">
|
2026-03-04 20:46:11 +00:00
|
|
|
<button type="submit" name="installer_action" value="test_smtp" class="button">Send Test Email + Run Checks</button>
|
|
|
|
|
<button type="submit" name="installer_action" value="finish_install" class="button button-primary">Finish Installation</button>
|
|
|
|
|
</div>
|
|
|
|
|
</form>
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
</section>
|
|
|
|
|
<?php
|
|
|
|
|
$content = ob_get_clean();
|
|
|
|
|
require __DIR__ . '/../../../views/site/layout.php';
|