prepare("SELECT * FROM video_sources WHERE id=? AND video_id=?"); $src->execute([$sid, $id]); $s = $src->fetch(); if ($s) { $f = MEDIA_DIR . $s['file_path']; if (file_exists($f)) unlink($f); $db->prepare("DELETE FROM video_sources WHERE id=?")->execute([$sid]); $msg = 'Source file removed.'; } $video = get_video_by_id($id); // refresh } if ($_SERVER['REQUEST_METHOD'] === 'POST') { $action = $_POST['action'] ?? 'save'; if ($action === 'save') { $title = trim($_POST['title'] ?? ''); $description = trim($_POST['description'] ?? ''); $duration = (int)($_POST['duration'] ?? 0); $sort_order = (int)($_POST['sort_order'] ?? 0); $published = isset($_POST['published']) ? 1 : 0; if (!$title) { $error = 'Title is required.'; } else { $slug = make_slug($title, $id); // Handle thumbnail replacement $thumbnail = $video['thumbnail']; if (!empty($_FILES['thumbnail']['tmp_name'])) { $ext = strtolower(pathinfo($_FILES['thumbnail']['name'], PATHINFO_EXTENSION)); $allowed = ['jpg','jpeg','png','webp','gif']; if (in_array($ext, $allowed)) { $thumb_dir = MEDIA_DIR . 'thumbs/'; if (!is_dir($thumb_dir)) mkdir($thumb_dir, 0755, true); // Remove old thumb if ($thumbnail && file_exists(MEDIA_DIR . $thumbnail)) unlink(MEDIA_DIR . $thumbnail); $fname = $slug . '_thumb_' . time() . '.' . $ext; if (move_uploaded_file($_FILES['thumbnail']['tmp_name'], $thumb_dir . $fname)) { $thumbnail = 'thumbs/' . $fname; } } else { $error = 'Thumbnail must be JPG, PNG, WebP, or GIF.'; } } if (!$error) { $db->prepare(" UPDATE videos SET title=?, description=?, slug=?, thumbnail=?, duration=?, sort_order=?, published=?, updated_at=datetime('now') WHERE id=? ")->execute([$title, $description, $slug, $thumbnail, $duration, $sort_order, $published, $id]); // Update existing sources sort/label/quality $upd_labels = $_POST['src_label'] ?? []; $upd_quality = $_POST['src_quality'] ?? []; $upd_sort = $_POST['src_sort'] ?? []; $upd_ids = $_POST['src_id'] ?? []; foreach ($upd_ids as $i => $sid) { $db->prepare("UPDATE video_sources SET label=?, quality=?, sort_order=? WHERE id=? AND video_id=?") ->execute([ $upd_labels[$i] ?? '', $upd_quality[$i] ?? '', (int)($upd_sort[$i] ?? $i), (int)$sid, $id ]); } // Add new source files $new_labels = $_POST['new_source_label'] ?? []; $new_quality = $_POST['new_source_quality'] ?? []; $new_sort = $_POST['new_source_sort'] ?? []; $new_files = $_FILES['new_source_file'] ?? []; $videos_dir = MEDIA_DIR . 'videos/'; if (!is_dir($videos_dir)) mkdir($videos_dir, 0755, true); $allowed_video = ['mp4','webm','ogv','ogg','mov','mkv','avi']; if (!empty($new_files['tmp_name'])) { foreach ($new_files['tmp_name'] as $i => $tmp) { if (empty($tmp) || !is_uploaded_file($tmp)) continue; $orig = $new_files['name'][$i]; $ext = strtolower(pathinfo($orig, PATHINFO_EXTENSION)); if (!in_array($ext, $allowed_video)) continue; $fname = $slug . '_' . time() . '_' . $i . '.' . $ext; if (move_uploaded_file($tmp, $videos_dir . $fname)) { $db->prepare("INSERT INTO video_sources (video_id,label,file_path,mime_type,quality,sort_order) VALUES (?,?,?,?,?,?)") ->execute([$id, trim($new_labels[$i] ?? ''), 'videos/' . $fname, mime_from_ext($fname), trim($new_quality[$i] ?? '720p'), (int)($new_sort[$i] ?? $i), ]); } } } header('Location: edit.php?id=' . $id . '&saved=1'); exit; } } } } // Refresh $video = get_video_by_id($id); render_head('Edit Video — Admin', ' .form-grid { display:grid; grid-template-columns:1fr; gap:1.2rem; } @media(min-width:700px) { .form-grid { grid-template-columns:1fr 1fr; } } .form-grid .span2 { grid-column:1/-1; } .section-heading { font-family:"Share Tech Mono",monospace; font-size:.65rem; letter-spacing:.15em; text-transform:uppercase; color:var(--text-3); margin-bottom:.75rem; } .hint { font-size:.72rem; color:var(--text-3); margin-top:.2rem; } .source-list { display:flex; flex-direction:column; gap:.75rem; } .source-item { background:var(--surface-2); border:1px solid var(--border); border-radius:var(--r); padding:.85rem 1rem; } .source-item-header { display:flex; align-items:center; justify-content:space-between; gap:.75rem; margin-bottom:.75rem; flex-wrap:wrap; } .source-item-file { font-family:"Share Tech Mono",monospace; font-size:.68rem; color:var(--text-2); word-break:break-all; } .source-item-mime { font-family:"Share Tech Mono",monospace; font-size:.6rem; color:var(--text-3); } .source-item-fields { display:grid; grid-template-columns:1fr 1fr 80px; gap:.6rem; } @media(max-width:600px) { .source-item-fields { grid-template-columns:1fr 1fr; } } .add-source-row { background:var(--surface-2); border:1px solid var(--border-2); border-radius:var(--r); padding:1rem; display:grid; grid-template-columns:1fr 1fr 1fr auto; gap:.75rem; align-items:end; } @media(max-width:700px) { .add-source-row { grid-template-columns:1fr 1fr; } } .admin-layout { display:grid; grid-template-columns:1fr; gap:1.5rem; } @media(min-width:900px) { .admin-layout { grid-template-columns:220px 1fr; } } .admin-nav { background:var(--surface); border:1px solid var(--border); border-radius:calc(var(--r)+2px); padding:1.2rem; display:flex; flex-direction:column; gap:.4rem; align-self:start; position:sticky; top:1rem; } .admin-nav-label { font-family:"Share Tech Mono",monospace; font-size:.58rem; letter-spacing:.18em; text-transform:uppercase; color:var(--text-3); margin-bottom:.3rem; padding-left:.5rem; } .admin-nav a { display:flex; align-items:center; gap:.6rem; padding:.55rem .75rem; border-radius:var(--r); font-size:.82rem; color:var(--text-2); text-decoration:none; transition:background .15s,color .15s; } .admin-nav a:hover { background:rgba(255,255,255,.05); color:var(--text); } .nav-divider { border:none; border-top:1px solid var(--border); margin:.4rem 0; } .thumb-preview { width:100%; max-width:240px; aspect-ratio:16/9; object-fit:cover; border-radius:var(--r); border:1px solid var(--border); background:var(--surface-2); display:block; margin-bottom:.5rem; } '); ?> Ty Clifford admin / edit video Preview Logout = h($msg) ?> = h($error) ?> Editing = h($video['title']) ?> ← Back Video Details Title * Description = h($video['description']) ?> Slug (auto-generated) Duration (seconds) Sort Order Published > Published Thumbnail Current: = h($video['thumbnail']) ?> Upload new image to replace current thumbnail. Existing Sources $s): ?> = h($s['file_path']) ?> = h($s['mime_type']) ?> Remove Quality >= $q ?: '—' ?> Label Sort Add New Source Files Upload additional formats (MP4, WebM, OGV, MOV, MKV, AVI). Video File Quality 1080p 720p 480p 360p 4K — Label Sort Add Another Format Save Changes Cancel
Editing
Video Details
Existing Sources
Add New Source Files
Upload additional formats (MP4, WebM, OGV, MOV, MKV, AVI).