fix(playback): isolate curriculum keys and prevent non-uploaded lessons from falling back to previous video

This commit is contained in:
Hamza-Ayed
2026-09-09 01:33:56 +03:00
parent a4d6e34a40
commit 78ad245ee5
4 changed files with 196 additions and 77 deletions
+41 -52
View File
@@ -533,14 +533,23 @@ class VideoController
// 1. Match by curriculum_key if provided
if ($curriculumKey !== '') {
$baseKey = basename($curriculumKeyNoExt);
$matched = Database::select(
"SELECT * FROM lessons
WHERE curriculum_key = ? OR curriculum_key = ?
OR curriculum_key LIKE ? OR local_path LIKE ? OR markdown_content LIKE ?
ORDER BY (hls_url IS NOT NULL AND hls_url != '') DESC, id DESC LIMIT 5",
[$curriculumKey, $curriculumKeyNoExt, '%' . $baseKey . '%', '%' . $curriculumKeyNoExt . '%', '%' . $curriculumKeyNoExt . '%']
);
if (str_contains($curriculumKeyNoExt, '/')) {
// Structured hierarchical key: match exact or qualified path suffix
$matched = Database::select(
"SELECT * FROM lessons
WHERE curriculum_key = ? OR curriculum_key = ?
OR curriculum_key LIKE ? OR local_path LIKE ? OR markdown_content LIKE ?
ORDER BY (hls_url IS NOT NULL AND hls_url != '') DESC, id DESC LIMIT 5",
[$curriculumKey, $curriculumKeyNoExt, "%{$curriculumKeyNoExt}%", "%{$curriculumKeyNoExt}%", "%{$curriculumKeyNoExt}%"]
);
} else {
$matched = Database::select(
"SELECT * FROM lessons
WHERE curriculum_key = ? OR curriculum_key LIKE ?
ORDER BY (hls_url IS NOT NULL AND hls_url != '') DESC, id DESC LIMIT 5",
[$curriculumKey, "%/{$curriculumKeyNoExt}%"]
);
}
if (!empty($matched)) {
$candidates = array_merge($candidates, $matched);
}
@@ -549,14 +558,16 @@ class VideoController
// 2. Match by title if provided
if (!empty($title)) {
$cleanTitle = trim(preg_replace('/^(الدرس\s*\d+:\s*|معملُ\s*[^:]+:\s*|مقدمة\s*[^:]+:\s*)/u', '', $title));
$matchedTitle = Database::select(
"SELECT * FROM lessons
WHERE title = ? OR title LIKE ? OR title LIKE ?
ORDER BY (hls_url IS NOT NULL AND hls_url != '') DESC, id DESC LIMIT 5",
[$title, "%{$title}%", "%{$cleanTitle}%"]
);
if (!empty($matchedTitle)) {
$candidates = array_merge($candidates, $matchedTitle);
if (mb_strlen($cleanTitle) >= 6) {
$matchedTitle = Database::select(
"SELECT * FROM lessons
WHERE title = ? OR title LIKE ?
ORDER BY (hls_url IS NOT NULL AND hls_url != '') DESC, id DESC LIMIT 5",
[$title, "%{$cleanTitle}%"]
);
if (!empty($matchedTitle)) {
$candidates = array_merge($candidates, $matchedTitle);
}
}
}
@@ -570,28 +581,17 @@ class VideoController
// 4. Manifest slug lookup
if (empty($candidates) && !empty($rawId)) {
$rawIdNoExt = preg_replace('/\.md$/i', '', $rawId);
$matchedRaw = Database::select(
"SELECT * FROM lessons
WHERE curriculum_key = ? OR curriculum_key = ? OR title LIKE ? OR local_path LIKE ? OR markdown_content LIKE ?
ORDER BY (hls_url IS NOT NULL AND hls_url != '') DESC, id DESC LIMIT 5",
[$rawId, $rawIdNoExt, "%{$rawId}%", "%{$rawIdNoExt}%", "%{$rawIdNoExt}%"]
);
if (!empty($matchedRaw)) {
$candidates = array_merge($candidates, $matchedRaw);
}
if (empty($candidates)) {
$manifestLesson = CurriculumService::findLessonById($rawId);
if ($manifestLesson && !empty($manifestLesson['title'])) {
$matchedManifest = Database::select(
"SELECT * FROM lessons
WHERE title = ? OR title LIKE ? OR markdown_content LIKE ?
ORDER BY (hls_url IS NOT NULL AND hls_url != '') DESC, id DESC LIMIT 5",
[$manifestLesson['title'], '%' . $manifestLesson['title'] . '%', '%' . ($manifestLesson['file'] ?? '') . '%']
);
if (!empty($matchedManifest)) {
$candidates = array_merge($candidates, $matchedManifest);
}
$manifestLesson = CurriculumService::findLessonById($rawId);
if ($manifestLesson && !empty($manifestLesson['file'])) {
$fileNoExt = preg_replace('/\.md$/i', '', $manifestLesson['file']);
$matchedManifest = Database::select(
"SELECT * FROM lessons
WHERE curriculum_key = ? OR curriculum_key = ? OR local_path LIKE ?
ORDER BY (hls_url IS NOT NULL AND hls_url != '') DESC, id DESC LIMIT 5",
[$manifestLesson['file'], $fileNoExt, "%{$fileNoExt}%"]
);
if (!empty($matchedManifest)) {
$candidates = array_merge($candidates, $matchedManifest);
}
}
}
@@ -604,24 +604,13 @@ class VideoController
break;
}
}
if (!$lesson) {
$lesson = $candidates[0];
}
}
if (!$lesson) {
// Fallback to latest available lesson in DB with a video
$lesson = Database::selectOne(
"SELECT * FROM lessons
WHERE hls_url IS NOT NULL AND hls_url != ''
ORDER BY id DESC LIMIT 1"
);
}
if (!$lesson) {
// Strict verification: if no matching lesson with an uploaded video is found, return 404
if (!$lesson || empty($lesson['hls_url'])) {
$response->status(404)->json([
'status' => 'error',
'message' => 'الدرس غير موجود أو لم يتم نشر الفيديو الخاص به بعد'
'message' => 'لم يتم رفع ونشر فيديو شرح لهذا الدرس بعد.'
]);
return;
}