Release v1.5.1

This commit is contained in:
AudioCore Bot
2026-04-01 14:12:17 +00:00
parent dc53051358
commit 9deabe1ec9
50 changed files with 10775 additions and 5637 deletions

View File

@@ -42,6 +42,9 @@ class AdminController
public function installer(): Response
{
if ($this->appInstalled()) {
return new Response('', 302, ['Location' => Auth::check() ? '/admin' : '/admin/login']);
}
$installer = $_SESSION['installer'] ?? [];
$step = !empty($installer['core_ready']) ? 2 : 1;
$values = is_array($installer['values'] ?? null) ? $installer['values'] : [];
@@ -61,6 +64,9 @@ class AdminController
public function install(): Response
{
if ($this->appInstalled()) {
return new Response('', 302, ['Location' => Auth::check() ? '/admin' : '/admin/login']);
}
$action = trim((string)($_POST['installer_action'] ?? 'setup_core'));
if ($action === 'setup_core') {
return $this->installSetupCore();
@@ -307,9 +313,9 @@ class AdminController
'title' => 'Settings',
'status' => $status,
'status_message' => $statusMessage,
'footer_text' => Settings::get('footer_text', 'AudioCore V1.5'),
'footer_text' => Settings::get('footer_text', 'AudioCore V1.5.1'),
'footer_links' => $this->parseFooterLinks(Settings::get('footer_links_json', '[]')),
'site_header_title' => Settings::get('site_header_title', 'AudioCore V1.5'),
'site_header_title' => Settings::get('site_header_title', 'AudioCore V1.5.1'),
'site_header_tagline' => Settings::get('site_header_tagline', 'Core CMS for DJs & Producers'),
'site_header_badge_text' => Settings::get('site_header_badge_text', 'Independent catalog'),
'site_header_brand_mode' => Settings::get('site_header_brand_mode', 'default'),
@@ -327,6 +333,7 @@ class AdminController
'site_maintenance_button_label' => Settings::get('site_maintenance_button_label', ''),
'site_maintenance_button_url' => Settings::get('site_maintenance_button_url', ''),
'site_maintenance_html' => Settings::get('site_maintenance_html', ''),
'site_maintenance_access_password_enabled' => Settings::get('site_maintenance_access_password_hash', '') !== '' ? '1' : '0',
'smtp_host' => Settings::get('smtp_host', ''),
'smtp_port' => Settings::get('smtp_port', '587'),
'smtp_user' => Settings::get('smtp_user', ''),
@@ -336,7 +343,7 @@ class AdminController
'smtp_from_name' => Settings::get('smtp_from_name', ''),
'mailchimp_api_key' => Settings::get('mailchimp_api_key', ''),
'mailchimp_list_id' => Settings::get('mailchimp_list_id', ''),
'seo_title_suffix' => Settings::get('seo_title_suffix', Settings::get('site_title', 'AudioCore V1.5')),
'seo_title_suffix' => Settings::get('seo_title_suffix', Settings::get('site_title', 'AudioCore V1.5.1')),
'seo_meta_description' => Settings::get('seo_meta_description', ''),
'seo_robots_index' => Settings::get('seo_robots_index', '1'),
'seo_robots_follow' => Settings::get('seo_robots_follow', '1'),
@@ -632,6 +639,8 @@ class AdminController
$maintenanceButtonLabel = trim((string)($_POST['site_maintenance_button_label'] ?? ''));
$maintenanceButtonUrl = trim((string)($_POST['site_maintenance_button_url'] ?? ''));
$maintenanceHtml = trim((string)($_POST['site_maintenance_html'] ?? ''));
$maintenanceAccessPassword = trim((string)($_POST['site_maintenance_access_password'] ?? ''));
$maintenanceAccessPasswordClear = isset($_POST['site_maintenance_access_password_clear']);
$smtpHost = trim((string)($_POST['smtp_host'] ?? ''));
$smtpPort = trim((string)($_POST['smtp_port'] ?? ''));
$smtpUser = trim((string)($_POST['smtp_user'] ?? ''));
@@ -675,6 +684,11 @@ class AdminController
Settings::set('site_maintenance_button_label', $maintenanceButtonLabel);
Settings::set('site_maintenance_button_url', $maintenanceButtonUrl);
Settings::set('site_maintenance_html', $maintenanceHtml);
if ($maintenanceAccessPasswordClear) {
Settings::set('site_maintenance_access_password_hash', '');
} elseif ($maintenanceAccessPassword !== '') {
Settings::set('site_maintenance_access_password_hash', password_hash($maintenanceAccessPassword, PASSWORD_DEFAULT));
}
Settings::set('smtp_host', $smtpHost);
Settings::set('smtp_port', $smtpPort);
Settings::set('smtp_user', $smtpUser);
@@ -769,7 +783,7 @@ class AdminController
}
$settingsPath = $storageDir . '/settings.php';
if (!is_file($settingsPath)) {
$settingsSeed = "<?php\nreturn [\n 'site_title' => 'AudioCore V1.5',\n];\n";
$settingsSeed = "<?php\nreturn [\n 'site_title' => 'AudioCore V1.5.1',\n];\n";
@file_put_contents($settingsPath, $settingsSeed);
}
$configPath = $storageDir . '/db.php';
@@ -925,7 +939,7 @@ class AdminController
];
$subject = 'AudioCore installer SMTP test';
$html = '<h2>SMTP test successful</h2><p>Your AudioCore V1.5 installer SMTP settings are valid.</p>'
$html = '<h2>SMTP test successful</h2><p>Your AudioCore V1.5.1 installer SMTP settings are valid.</p>'
. '<p><strong>Generated:</strong> ' . gmdate('Y-m-d H:i:s') . ' UTC</p>';
$mail = Mailer::send($testEmail, $subject, $html, $smtpSettings);
@@ -1028,9 +1042,9 @@ class AdminController
private function installerDefaultValues(): array
{
return [
'site_title' => 'AudioCore V1.5',
'site_title' => 'AudioCore V1.5.1',
'site_tagline' => 'Core CMS for DJs & Producers',
'seo_title_suffix' => 'AudioCore V1.5',
'seo_title_suffix' => 'AudioCore V1.5.1',
'seo_meta_description' => 'Independent catalog platform for artists, releases, store, and support.',
'smtp_host' => '',
'smtp_port' => '587',
@@ -1038,7 +1052,7 @@ class AdminController
'smtp_pass' => '',
'smtp_encryption' => 'tls',
'smtp_from_email' => '',
'smtp_from_name' => 'AudioCore V1.5',
'smtp_from_name' => 'AudioCore V1.5.1',
];
}
@@ -1664,6 +1678,24 @@ class AdminController
return Database::get() instanceof PDO;
}
private function appInstalled(): bool
{
$db = Database::get();
if (!$db instanceof PDO) {
return false;
}
$this->ensureCoreTables();
try {
$adminUsers = (int)$db->query("SELECT COUNT(*) FROM ac_admin_users")->fetchColumn();
$legacyAdmins = (int)$db->query("SELECT COUNT(*) FROM ac_admins")->fetchColumn();
return ($adminUsers + $legacyAdmins) > 0;
} catch (Throwable $e) {
return false;
}
}
private function normalizeUrl(string $url): string
{
if (preg_match('~^(https?://|/|#|mailto:)~i', $url)) {

View File

@@ -136,7 +136,7 @@ ob_start();
<section class="card ac-installer">
<div class="badge">Setup</div>
<h1 class="ac-installer-title">AudioCore V1.5 Installer</h1>
<h1 class="ac-installer-title">AudioCore V1.5.1 Installer</h1>
<p class="ac-installer-intro">Deploy a fresh instance with validated SMTP and baseline health checks.</p>
<div class="ac-installer-steps">
@@ -201,7 +201,7 @@ ob_start();
<div class="ac-installer-grid">
<div>
<label>Site Title *</label>
<input class="input" name="site_title" value="<?= htmlspecialchars($val('site_title', 'AudioCore V1.5'), ENT_QUOTES, 'UTF-8') ?>">
<input class="input" name="site_title" value="<?= htmlspecialchars($val('site_title', 'AudioCore V1.5.1'), ENT_QUOTES, 'UTF-8') ?>">
</div>
<div>
<label>Site Tagline</label>
@@ -209,7 +209,7 @@ ob_start();
</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') ?>">
<input class="input" name="seo_title_suffix" value="<?= htmlspecialchars($val('seo_title_suffix', 'AudioCore V1.5.1'), ENT_QUOTES, 'UTF-8') ?>">
</div>
<div style="grid-column:1/-1;">
<label>SEO Meta Description</label>
@@ -244,7 +244,7 @@ ob_start();
</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') ?>">
<input class="input" name="smtp_from_name" value="<?= htmlspecialchars($val('smtp_from_name', 'AudioCore V1.5.1'), ENT_QUOTES, 'UTF-8') ?>">
</div>
<div>
<label>Test Recipient Email *</label>

File diff suppressed because it is too large Load Diff

View File

@@ -32,7 +32,7 @@ ob_start();
<div class="badge" style="opacity:0.7;">Branding</div>
<div style="margin-top:12px; display:grid; gap:12px;">
<label class="label">Header Title</label>
<input class="input" name="site_header_title" value="<?= htmlspecialchars($site_header_title ?? '', ENT_QUOTES, 'UTF-8') ?>" placeholder="AudioCore V1.5">
<input class="input" name="site_header_title" value="<?= htmlspecialchars($site_header_title ?? '', ENT_QUOTES, 'UTF-8') ?>" placeholder="AudioCore V1.5.1">
<label class="label">Header Tagline</label>
<input class="input" name="site_header_tagline" value="<?= htmlspecialchars($site_header_tagline ?? '', ENT_QUOTES, 'UTF-8') ?>" placeholder="Core CMS for DJs & Producers">
@@ -120,7 +120,7 @@ ob_start();
<div class="badge" style="opacity:0.7;">Footer</div>
<div style="margin-top:12px; display:grid; gap:12px;">
<label class="label">Footer Text</label>
<input class="input" name="footer_text" value="<?= htmlspecialchars($footer_text ?? '', ENT_QUOTES, 'UTF-8') ?>" placeholder="AudioCore V1.5">
<input class="input" name="footer_text" value="<?= htmlspecialchars($footer_text ?? '', ENT_QUOTES, 'UTF-8') ?>" placeholder="AudioCore V1.5.1">
<div style="font-size:12px; color:var(--muted);">Shown in the site footer.</div>
<div class="label">Footer Links</div>
@@ -158,6 +158,17 @@ ob_start();
<input class="input" name="site_maintenance_button_url" value="<?= htmlspecialchars($site_maintenance_button_url ?? '', ENT_QUOTES, 'UTF-8') ?>" placeholder="/admin/login">
</div>
</div>
<div style="display:grid; gap:10px; padding:14px; border:1px solid rgba(255,255,255,.08); border-radius:16px; background:rgba(255,255,255,.02);">
<div class="badge" style="opacity:.7;">Visitor Access Password</div>
<div style="font-size:12px; color:var(--muted);">
Set a password to let non-admin users unlock the site during maintenance mode. Leave blank to keep the current password.
</div>
<input class="input" type="password" name="site_maintenance_access_password" placeholder="<?= (($site_maintenance_access_password_enabled ?? '0') === '1') ? 'Password already set - enter a new one to replace it' : 'Set an access password' ?>">
<label style="display:inline-flex; align-items:center; gap:8px; font-size:13px;">
<input type="checkbox" name="site_maintenance_access_password_clear" value="1">
Clear the current access password
</label>
</div>
<label class="label">Custom HTML (optional, overrides title/message layout)</label>
<textarea class="input" name="site_maintenance_html" rows="6" style="resize:vertical; font-family:'IBM Plex Mono', monospace;"><?= htmlspecialchars($site_maintenance_html ?? '', ENT_QUOTES, 'UTF-8') ?></textarea>
</div>
@@ -218,7 +229,7 @@ ob_start();
<div class="badge" style="opacity:0.7;">Global SEO</div>
<div style="margin-top:12px; display:grid; gap:12px;">
<label class="label">Title Suffix</label>
<input class="input" name="seo_title_suffix" value="<?= htmlspecialchars($seo_title_suffix ?? '', ENT_QUOTES, 'UTF-8') ?>" placeholder="AudioCore V1.5">
<input class="input" name="seo_title_suffix" value="<?= htmlspecialchars($seo_title_suffix ?? '', ENT_QUOTES, 'UTF-8') ?>" placeholder="AudioCore V1.5.1">
<label class="label">Default Meta Description</label>
<textarea class="input" name="seo_meta_description" rows="3" style="resize:vertical;"><?= htmlspecialchars($seo_meta_description ?? '', ENT_QUOTES, 'UTF-8') ?></textarea>
<label class="label">Open Graph Image URL</label>