Update Saqel Platform: 2026-08-29 22:41:36
This commit is contained in:
@@ -261,7 +261,10 @@ class CurriculumController
|
||||
}
|
||||
|
||||
try {
|
||||
$courseId = 0; // System course ID for curriculum AI videos
|
||||
// Resolve a valid FK-safe course_id for the master ministry curriculum.
|
||||
// IMPORTANT: course_id = 0 causes SQLSTATE[23000] FK violation because
|
||||
// the `lessons` table enforces courses(id) ON DELETE CASCADE.
|
||||
$courseId = CurriculumService::getOrCreateSystemCourse();
|
||||
$title = basename($file, '.md');
|
||||
|
||||
// 1. Upload & Transcode to HLS & Push to R2 (handled by VideoService)
|
||||
@@ -269,7 +272,7 @@ class CurriculumController
|
||||
|
||||
$videoUrl = $uploadResult['r2_url'] ?? $uploadResult['hls_url'];
|
||||
|
||||
// 2. Insert into lessons table as AI generated version
|
||||
// 2. Insert into lessons table as AI-generated ministry version
|
||||
$lessonId = \App\Core\Database::insert(
|
||||
"INSERT INTO lessons (course_id, title, sequence_order, storage_type, video_uuid, bunny_video_id, local_path, hls_url, thumbnail_url, duration_seconds, is_free_preview, encoding_status, ai_video_url)
|
||||
VALUES (?, ?, 1, 'api_upload', ?, '', ?, ?, ?, ?, 0, 'ready', ?)",
|
||||
@@ -307,6 +310,8 @@ class CurriculumController
|
||||
'status' => 'success',
|
||||
'message' => 'تم رفع وتثبيت فيديو الشرح ومعالجته HLS وربطه بالذكاء الاصطناعي بنجاح!',
|
||||
'video_url' => $videoUrl,
|
||||
'course_id' => $courseId,
|
||||
'lesson_id' => $lessonId,
|
||||
'data' => $uploadResult
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
|
||||
@@ -306,23 +306,73 @@ class VideoController
|
||||
VideoService::ensureSchema();
|
||||
CurriculumService::ensureSchema();
|
||||
|
||||
$courseId = (int)($request->getQuery('course_id') ?: 0);
|
||||
$where = $courseId > 0 ? "WHERE l.course_id = {$courseId}" : "";
|
||||
$courseId = (int)($request->getQuery('course_id') ?: 0);
|
||||
|
||||
// Extract student grade/stream from JWT-decoded context (populated by auth middleware)
|
||||
$gradeLevel = $request->getQuery('grade_level') ?: ($request->user['grade_level'] ?? null);
|
||||
$stream = $request->getQuery('stream') ?: ($request->user['stream'] ?? null);
|
||||
$schoolId = $request->user['school_id'] ?? null;
|
||||
|
||||
// Build WHERE clause dynamically
|
||||
$conditions = [];
|
||||
$params = [];
|
||||
|
||||
if ($courseId > 0) {
|
||||
$conditions[] = 'l.course_id = ?';
|
||||
$params[] = $courseId;
|
||||
}
|
||||
|
||||
// Grade/stream filter: include lessons where the course matches the student's
|
||||
// grade/stream, OR where the course is the system curriculum (AI videos).
|
||||
// This ensures AI ministry content is always visible to all students.
|
||||
if ($gradeLevel || $stream) {
|
||||
$gradeCond = '(c.is_system_curriculum = 1';
|
||||
if ($gradeLevel) {
|
||||
$gradeCond .= ' OR c.grade_level = ?';
|
||||
$params[] = $gradeLevel;
|
||||
}
|
||||
if ($stream) {
|
||||
$gradeCond .= ' OR c.stream = ?';
|
||||
$params[] = $stream;
|
||||
}
|
||||
$gradeCond .= ')';
|
||||
$conditions[] = $gradeCond;
|
||||
}
|
||||
|
||||
$whereClause = !empty($conditions) ? ('WHERE ' . implode(' AND ', $conditions)) : '';
|
||||
|
||||
$lessons = Database::select(
|
||||
"SELECT l.id, l.course_id, l.title, l.sequence_order, l.storage_type, l.video_uuid, l.hls_url, l.thumbnail_url,
|
||||
"SELECT l.id, l.course_id, l.title, l.sequence_order, l.storage_type,
|
||||
l.video_uuid, l.hls_url, l.thumbnail_url, l.ai_video_url,
|
||||
l.duration_seconds, l.is_free_preview, l.created_at,
|
||||
COALESCE(c.title, 'توجيهي 2008 — المنهاج المعتمد') as course_title,
|
||||
COALESCE(c.is_system_curriculum, 0) as is_ai_version,
|
||||
c.teacher_id,
|
||||
u.full_name as teacher_name,
|
||||
c.school_id,
|
||||
CASE WHEN c.school_id = ? THEN 1 ELSE 0 END as is_my_school,
|
||||
(SELECT COUNT(*) FROM exams WHERE lesson_id = l.id AND scope = 'in_video_checkpoint') as checkpoints_count
|
||||
FROM lessons l
|
||||
LEFT JOIN courses c ON l.course_id = c.id
|
||||
{$where}
|
||||
ORDER BY l.id DESC"
|
||||
LEFT JOIN users u ON c.teacher_id = u.id
|
||||
{$whereClause}
|
||||
ORDER BY is_ai_version DESC, is_my_school DESC, l.sequence_order ASC, l.id DESC",
|
||||
array_merge([$schoolId ?? 0], $params)
|
||||
);
|
||||
|
||||
// Separate AI/ministry lessons from teacher lessons for the carousel
|
||||
$aiLessons = array_filter($lessons, fn($l) => (bool)$l['is_ai_version']);
|
||||
$teacherLessons = array_filter($lessons, fn($l) => !(bool)$l['is_ai_version']);
|
||||
|
||||
$response->json([
|
||||
'status' => 'success',
|
||||
'data' => $lessons
|
||||
'data' => array_values($lessons),
|
||||
'meta' => [
|
||||
'grade_level' => $gradeLevel,
|
||||
'stream' => $stream,
|
||||
'ai_count' => count($aiLessons),
|
||||
'teacher_count' => count($teacherLessons),
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user