Files
MyKeyser/includes/functions.php
T
2026-06-18 12:50:44 -04:00

152 lines
7.2 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/* ── Auth ─────────────────────────────────────────────── */
function uid(): int { return (int)($_SESSION['uid'] ?? 0); }
function uname(): string{ return (string)($_SESSION['uname'] ?? ''); }
function authed(): bool { return uid() > 0; }
function isAdmin(): bool{ return !empty($_SESSION['admin']); }
function requireLogin(string $back = ''): void {
if (!authed()) {
flash('Please log in to continue.', 'warning');
go('/login.php?next='.urlencode($back ?: $_SERVER['REQUEST_URI']));
}
}
function requireAdmin(): void {
if (!isAdmin()) { flash('Access denied.', 'error'); go('/index.php'); }
}
function loginUser(array $u): void {
session_regenerate_id(true);
$_SESSION['uid'] = $u['id'];
$_SESSION['uname'] = $u['username'];
$_SESSION['admin'] = (bool)$u['is_admin'];
qrun("UPDATE users SET last_login=datetime('now') WHERE id=?", [$u['id']]);
}
function logoutUser(): void {
session_unset(); session_destroy();
session_start(); session_regenerate_id(true);
}
/* ── Flash ────────────────────────────────────────────── */
function flash(string $msg, string $type = 'info'): void { $_SESSION['_flash'][] = [$type, $msg]; }
function getFlashes(): array { $f = $_SESSION['_flash'] ?? []; unset($_SESSION['_flash']); return $f; }
/* ── Output ───────────────────────────────────────────── */
function e(mixed $v): string { return htmlspecialchars((string)($v ?? ''), ENT_QUOTES|ENT_SUBSTITUTE, 'UTF-8'); }
function go(string $url): never { header('Location:'.$url); exit; }
/* ── Input ────────────────────────────────────────────── */
function p(string $k, mixed $d = ''): mixed { return $_POST[$k] ?? $d; }
function g(string $k, mixed $d = ''): mixed { return $_GET[$k] ?? $d; }
function iget(string $k): int { return (int)($_POST[$k] ?? $_GET[$k] ?? 0); }
function ps(string $k): string { return trim((string)($_POST[$k] ?? '')); }
function gs(string $k): string { return trim((string)($_GET[$k] ?? '')); }
function isPost(): bool { return strtoupper($_SERVER['REQUEST_METHOD']) === 'POST'; }
/* ── CSRF ─────────────────────────────────────────────── */
function csrf(): string {
if (empty($_SESSION['csrf'])) $_SESSION['csrf'] = bin2hex(random_bytes(24));
return $_SESSION['csrf'];
}
function csrfField(): string { return '<input type="hidden" name="_csrf" value="'.e(csrf()).'">'; }
function csrfCheck(): void {
if (!hash_equals(csrf(), p('_csrf', ''))) { http_response_code(403); die('Invalid CSRF token.'); }
}
/* ── Settings ─────────────────────────────────────────── */
function setting(string $k, string $def = ''): string {
$v = qval("SELECT value FROM settings WHERE key=?", [$k]);
return ($v !== false && $v !== null) ? (string)$v : $def;
}
function setSetting(string $k, string $v): void {
qrun("INSERT INTO settings(key,value)VALUES(?,?)ON CONFLICT(key)DO UPDATE SET value=excluded.value", [$k,$v]);
}
/* ── Ownership ────────────────────────────────────────── */
function owns(int $bizId): bool {
if (isAdmin()) return true;
if (!authed()) return false;
return (bool)qval("SELECT 1 FROM business_owners WHERE user_id=? AND business_id=?", [uid(),$bizId]);
}
/* ── Stars ────────────────────────────────────────────── */
function starDisplay(float $avg): string {
$r = (int)round($avg);
$out = '<span class="stars">';
for ($i = 1; $i <= 5; $i++) $out .= '<span class="star'.($i<=$r?' on':'').'">★</span>';
return $out.'</span>';
}
function starPicker(string $name = 'rating', int $sel = 0): string {
$out = '<div class="star-picker">';
for ($i = 5; $i >= 1; $i--) {
$chk = $sel === $i ? 'checked' : '';
$out .= '<input type="radio" id="sr'.$i.'" name="'.$name.'" value="'.$i.'" '.$chk.'>';
$out .= '<label for="sr'.$i.'">★</label>';
}
return $out.'</div>';
}
/* ── Date / Money ─────────────────────────────────────── */
function ago(mixed $dt): string {
if ($dt === null || $dt === '' || $dt === false) return '';
$ts = is_int($dt) ? $dt : @strtotime((string)$dt);
if (!$ts) return '';
$d = time() - $ts;
if ($d < 60) return 'Just now';
if ($d < 3600) return floor($d / 60).'m ago';
if ($d < 86400) return floor($d / 3600).'h ago';
if ($d < 604800) return floor($d / 86400).'d ago';
return date('M j, Y', $ts);
}
function fdate(mixed $dt, string $fmt = 'M j, Y'): string {
if ($dt === null || $dt === '' || $dt === false) return '';
$ts = is_int($dt) ? $dt : @strtotime((string)$dt);
return $ts ? date($fmt, $ts) : '';
}
function money(float $n): string { return '$'.number_format($n, 2); }
/* ── Misc ─────────────────────────────────────────────── */
function alertIcon(mixed $t): string {
return match((string)($t ?? '')) {
'news' => '📰',
'event' => '🎉',
'warning' => '⚠️',
'sale' => '🏷️',
default => '️',
};
}
function parseHours(mixed $json): array {
$s = (string)($json ?? '');
if ($s === '' || $s === '[]' || $s === 'null') return [];
$decoded = json_decode($s, true);
if (!is_array($decoded)) return [];
// Must be an object (associative), not a plain list
foreach (array_keys($decoded) as $key) {
if (!is_string($key)) return [];
}
return $decoded;
}
function makeSlug(string $s): string {
return trim(preg_replace('/[^a-z0-9]+/', '-', strtolower($s)), '-');
}
function uniqueSlug(string $base): string {
$slug = makeSlug($base); $i = 0;
while (qval("SELECT id FROM businesses WHERE slug=?", [$slug.($i ? "-$i" : "")])) $i++;
return $slug . ($i ? "-$i" : "");
}
function businessVideoProvider(string $url): string {
$host = strtolower((string)(parse_url(trim($url), PHP_URL_HOST) ?? ''));
$host = preg_replace('/^www\./', '', $host);
if ($host === 'youtu.be' || $host === 'youtube.com' || str_ends_with($host, '.youtube.com') || $host === 'youtube-nocookie.com' || str_ends_with($host, '.youtube-nocookie.com')) return 'YouTube';
if ($host === 'vimeo.com' || str_ends_with($host, '.vimeo.com')) return 'Vimeo';
return '';
}
function validBusinessVideoUrl(string $url): bool {
$url = trim($url);
if ($url === '') return true;
$scheme = strtolower((string)(parse_url($url, PHP_URL_SCHEME) ?? ''));
return in_array($scheme, ['http','https'], true) && businessVideoProvider($url) !== '';
}