-
This commit is contained in:
+168
@@ -0,0 +1,168 @@
|
||||
<?php
|
||||
/**
|
||||
* db.php — SQLite database bootstrap & helpers
|
||||
*/
|
||||
|
||||
define('DB_PATH', __DIR__ . '/../data/media.db');
|
||||
define('MEDIA_DIR', __DIR__ . '/../media/');
|
||||
define('MEDIA_URL', 'media/');
|
||||
|
||||
function get_db(): PDO {
|
||||
static $pdo = null;
|
||||
if ($pdo) return $pdo;
|
||||
|
||||
$dir = dirname(DB_PATH);
|
||||
if (!is_dir($dir)) mkdir($dir, 0755, true);
|
||||
|
||||
$pdo = new PDO('sqlite:' . DB_PATH);
|
||||
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
|
||||
$pdo->exec('PRAGMA journal_mode=WAL');
|
||||
$pdo->exec('PRAGMA foreign_keys=ON');
|
||||
|
||||
// Schema
|
||||
$pdo->exec("
|
||||
CREATE TABLE IF NOT EXISTS settings (
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS videos (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
title TEXT NOT NULL DEFAULT 'Untitled',
|
||||
description TEXT NOT NULL DEFAULT '',
|
||||
slug TEXT NOT NULL UNIQUE,
|
||||
thumbnail TEXT NOT NULL DEFAULT '',
|
||||
duration INTEGER NOT NULL DEFAULT 0,
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
published INTEGER NOT NULL DEFAULT 1,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS video_sources (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
video_id INTEGER NOT NULL REFERENCES videos(id) ON DELETE CASCADE,
|
||||
label TEXT NOT NULL DEFAULT '',
|
||||
file_path TEXT NOT NULL,
|
||||
mime_type TEXT NOT NULL DEFAULT 'video/mp4',
|
||||
quality TEXT NOT NULL DEFAULT '720p',
|
||||
sort_order INTEGER NOT NULL DEFAULT 0
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_videos_published ON videos(published);
|
||||
CREATE INDEX IF NOT EXISTS idx_videos_sort ON videos(sort_order, id);
|
||||
CREATE INDEX IF NOT EXISTS idx_sources_video ON video_sources(video_id);
|
||||
");
|
||||
|
||||
// Default settings
|
||||
$defaults = [
|
||||
'catalogue_per_page' => '10',
|
||||
'admin_password' => password_hash('admin', PASSWORD_DEFAULT),
|
||||
'site_title' => 'Ty Clifford',
|
||||
'site_sub' => 'tyclifford.com / media',
|
||||
];
|
||||
$ins = $pdo->prepare("INSERT OR IGNORE INTO settings (key, value) VALUES (?, ?)");
|
||||
foreach ($defaults as $k => $v) $ins->execute([$k, $v]);
|
||||
|
||||
return $pdo;
|
||||
}
|
||||
|
||||
function setting(string $key, string $fallback = ''): string {
|
||||
$row = get_db()->prepare("SELECT value FROM settings WHERE key=?");
|
||||
$row->execute([$key]);
|
||||
$r = $row->fetch();
|
||||
return $r ? $r['value'] : $fallback;
|
||||
}
|
||||
|
||||
function set_setting(string $key, string $value): void {
|
||||
get_db()->prepare("INSERT OR REPLACE INTO settings (key,value) VALUES (?,?)")
|
||||
->execute([$key, $value]);
|
||||
}
|
||||
|
||||
function make_slug(string $title, int $id = 0): string {
|
||||
$slug = strtolower(trim(preg_replace('/[^a-z0-9]+/i', '-', $title), '-'));
|
||||
if ($id) {
|
||||
$exists = get_db()->prepare("SELECT id FROM videos WHERE slug=? AND id!=?");
|
||||
$exists->execute([$slug, $id]);
|
||||
} else {
|
||||
$exists = get_db()->prepare("SELECT id FROM videos WHERE slug=?");
|
||||
$exists->execute([$slug]);
|
||||
}
|
||||
if ($exists->fetch()) $slug .= '-' . ($id ?: time());
|
||||
return $slug ?: 'video-' . time();
|
||||
}
|
||||
|
||||
function mime_from_ext(string $path): string {
|
||||
$ext = strtolower(pathinfo($path, PATHINFO_EXTENSION));
|
||||
return match($ext) {
|
||||
'mp4' => 'video/mp4',
|
||||
'webm' => 'video/webm',
|
||||
'ogv' => 'video/ogg',
|
||||
'mov' => 'video/quicktime',
|
||||
'mkv' => 'video/x-matroska',
|
||||
'avi' => 'video/x-msvideo',
|
||||
default => 'video/mp4',
|
||||
};
|
||||
}
|
||||
|
||||
function format_duration(int $seconds): string {
|
||||
if ($seconds <= 0) return '';
|
||||
$h = intdiv($seconds, 3600);
|
||||
$m = intdiv($seconds % 3600, 60);
|
||||
$s = $seconds % 60;
|
||||
if ($h) return sprintf('%d:%02d:%02d', $h, $m, $s);
|
||||
return sprintf('%d:%02d', $m, $s);
|
||||
}
|
||||
|
||||
function h(string $s): string {
|
||||
return htmlspecialchars($s, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
|
||||
}
|
||||
|
||||
function get_videos_paginated(int $page, int $per_page, bool $published_only = true): array {
|
||||
$db = get_db();
|
||||
$where = $published_only ? 'WHERE v.published=1' : '';
|
||||
$offset = ($page - 1) * $per_page;
|
||||
$total = $db->query("SELECT COUNT(*) FROM videos v $where")->fetchColumn();
|
||||
$rows = $db->prepare("
|
||||
SELECT v.*, GROUP_CONCAT(vs.file_path,'||') AS source_paths
|
||||
FROM videos v
|
||||
LEFT JOIN video_sources vs ON vs.video_id = v.id
|
||||
$where
|
||||
GROUP BY v.id
|
||||
ORDER BY v.sort_order ASC, v.id DESC
|
||||
LIMIT ? OFFSET ?
|
||||
");
|
||||
$rows->execute([$per_page, $offset]);
|
||||
return [
|
||||
'videos' => $rows->fetchAll(),
|
||||
'total' => (int)$total,
|
||||
'page' => $page,
|
||||
'per_page' => $per_page,
|
||||
'total_pages' => (int)ceil($total / $per_page),
|
||||
];
|
||||
}
|
||||
|
||||
function get_video_by_slug(string $slug): ?array {
|
||||
$db = get_db();
|
||||
$row = $db->prepare("SELECT * FROM videos WHERE slug=? AND published=1");
|
||||
$row->execute([$slug]);
|
||||
$v = $row->fetch();
|
||||
if (!$v) return null;
|
||||
$sources = $db->prepare("SELECT * FROM video_sources WHERE video_id=? ORDER BY sort_order ASC");
|
||||
$sources->execute([$v['id']]);
|
||||
$v['sources'] = $sources->fetchAll();
|
||||
return $v;
|
||||
}
|
||||
|
||||
function get_video_by_id(int $id): ?array {
|
||||
$db = get_db();
|
||||
$row = $db->prepare("SELECT * FROM videos WHERE id=?");
|
||||
$row->execute([$id]);
|
||||
$v = $row->fetch();
|
||||
if (!$v) return null;
|
||||
$sources = $db->prepare("SELECT * FROM video_sources WHERE video_id=? ORDER BY sort_order ASC");
|
||||
$sources->execute([$v['id']]);
|
||||
$v['sources'] = $sources->fetchAll();
|
||||
return $v;
|
||||
}
|
||||
Reference in New Issue
Block a user