Update Saqel Platform: 2026-09-08 13:43:36

This commit is contained in:
Hamza-Ayed
2026-09-08 13:43:36 +03:00
parent 0f424062fe
commit bb37b31cab
76 changed files with 3617 additions and 3059 deletions
+31 -27
View File
@@ -43,38 +43,53 @@ class VideoController
$title = trim((string)($request->getBody()['title'] ?? $_POST['title'] ?? ''));
$seqOrder = (int)($request->getBody()['sequence_order'] ?? $_POST['sequence_order'] ?? 1);
if (!$courseId || empty($title)) {
if (empty($title)) {
$response->status(400)->json([
'status' => 'error',
'message' => 'معرف الدورة وعنوان الدرس مطلوبان'
'message' => 'عنوان الدرس مطلوب'
]);
return;
}
// Verify Course Ownership / Permissions (or auto-resolve/create for teacher)
$course = Database::selectOne("SELECT id, teacher_id FROM courses WHERE id = ? LIMIT 1", [$courseId]);
if (!$course) {
// Resolve a teacher-owned course when the app did not explicitly select one.
$course = null;
if ($courseId > 0) {
$course = Database::selectOne("SELECT id, teacher_id FROM courses WHERE id = ? LIMIT 1", [$courseId]);
if (!$course) {
$response->status(404)->json(['status' => 'error', 'message' => 'الدورة المطلوبة غير موجودة']);
return;
}
if ((int)$course['teacher_id'] !== (int)$request->user_id && $request->role !== 'super_admin') {
$response->status(403)->json(['status' => 'error', 'message' => 'لا تملك صلاحية رفع محتوى لهذه الدورة']);
return;
}
} else {
$existingCourse = Database::selectOne("SELECT id, teacher_id FROM courses WHERE teacher_id = ? LIMIT 1", [$request->user_id]);
if ($existingCourse) {
$courseId = (int)$existingCourse['id'];
$course = $existingCourse;
} else {
$subjectName = trim((string)($request->getBody()['subject'] ?? $_POST['subject'] ?? ''));
$gradeLevel = trim((string)($request->getBody()['grade_level'] ?? $_POST['grade_level'] ?? ''));
$subject = Database::selectOne(
"SELECT id FROM subjects WHERE name_ar = ? OR name_en = ? ORDER BY id LIMIT 1",
[$subjectName, $subjectName]
) ?: Database::selectOne("SELECT id FROM subjects ORDER BY id LIMIT 1");
if (!$subject) {
$response->status(409)->json(['status' => 'error', 'message' => 'لا يوجد مبحث معرف لربط الفيديو به']);
return;
}
$cUuid = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0x0fff) | 0x4000, mt_rand(0, 0x3fff) | 0x8000, mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff));
$newCourseId = Database::insert(
"INSERT INTO courses (uuid, teacher_id, subject_id, title, description, semester, price_jod, is_published)
VALUES (?, ?, 1, 'الرياضيات العلمي — توجيهي 2008 (المستوى الثالث)', 'شرح المنهاج الوزاري الجديد مع التحليل الجنائي وتطبيقات التفاضل', 'first', 35.00, 1)",
[$cUuid, $request->user_id]
"INSERT INTO courses (uuid, teacher_id, subject_id, title, description, semester, price_jod, is_published, grade_level)
VALUES (?, ?, ?, ?, '', 'first', 0.00, 0, ?)",
[$cUuid, $request->user_id, (int)$subject['id'], $title, $gradeLevel]
);
$courseId = $newCourseId;
$course = ['id' => $newCourseId, 'teacher_id' => $request->user_id];
}
}
// If authenticated teacher, bind course ownership
if ($request->role === 'teacher' && $course['teacher_id'] != $request->user_id) {
Database::query("UPDATE courses SET teacher_id = ? WHERE id = ?", [$request->user_id, $courseId]);
}
if (empty($_FILES['video'])) {
$response->status(400)->json([
'status' => 'error',
@@ -577,16 +592,8 @@ class VideoController
'is_ready' => true,
];
} else {
// High-Performance Educational Video Streaming Stream (Reliable Sample Stream)
$defaultVideoUrl = 'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4';
$playbackInfo = [
'storage_type' => 'educational_stream',
'video_url' => $defaultVideoUrl,
'hls_url' => $defaultVideoUrl,
'stream_url' => $defaultVideoUrl,
'is_ready' => true,
'notice' => 'جاري تشغيل البث التعليمي النموذجي المعتمد للدرس',
];
$response->status(409)->json(['status' => 'error', 'message' => 'لم يتم ربط فيديو R2 جاهز بهذا الدرس بعد']);
return;
}
$chapters = !empty($lesson['timeline_chapters_json']) ? json_decode($lesson['timeline_chapters_json'], true) : [];
@@ -621,10 +628,7 @@ class VideoController
} else {
$bId = $ver['bunny_video_id'] ?: '';
if ($bId === '') {
$vPlayback = [
'storage_type' => 'educational_stream',
'video_url' => 'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4'
];
continue;
} else {
$signed = VideoService::generateBunnySignedPlayback($bId, 10800);
$vPlayback = array_merge(['storage_type' => 'bunny_stream', 'video_url' => $signed['hls_url']], $signed);