Update Saqel Platform: 2026-09-02 07:43:58
This commit is contained in:
@@ -264,29 +264,35 @@ class CurriculumController
|
||||
// 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');
|
||||
$manifestLesson = CurriculumService::findLessonByFile($file);
|
||||
$title = $manifestLesson['title'] ?? basename($file, '.md');
|
||||
$existingLesson = \App\Core\Database::selectOne(
|
||||
"SELECT id, course_id FROM lessons WHERE title = ? OR markdown_content LIKE ? LIMIT 1",
|
||||
[$title, '%' . $file . '%']
|
||||
);
|
||||
$courseId = $existingLesson
|
||||
? (int)$existingLesson['course_id']
|
||||
: CurriculumService::getOrCreateSystemCourse();
|
||||
|
||||
// 1. Upload & Transcode to HLS & Push to R2 (handled by VideoService)
|
||||
$uploadResult = \App\Services\VideoService::handleDirectUpload($_FILES['video_file'], $courseId, $title);
|
||||
|
||||
$videoUrl = $uploadResult['r2_url'] ?? $uploadResult['hls_url'];
|
||||
|
||||
// 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', ?)",
|
||||
[
|
||||
$courseId,
|
||||
$title,
|
||||
$uploadResult['video_uuid'],
|
||||
$uploadResult['local_path'],
|
||||
$uploadResult['hls_url'],
|
||||
$uploadResult['thumbnail_url'],
|
||||
$uploadResult['duration'] ?? 0,
|
||||
$videoUrl
|
||||
]
|
||||
);
|
||||
// 2. Bind the upload to the synchronized Manifest lesson when present.
|
||||
if ($existingLesson) {
|
||||
$lessonId = (int)$existingLesson['id'];
|
||||
\App\Core\Database::query(
|
||||
"UPDATE lessons SET storage_type = 'api_upload', video_uuid = ?, bunny_video_id = '', local_path = ?, hls_url = ?, thumbnail_url = ?, duration_seconds = ?, encoding_status = 'ready', ai_video_url = ? WHERE id = ?",
|
||||
[$uploadResult['video_uuid'], $uploadResult['local_path'], $uploadResult['hls_url'], $uploadResult['thumbnail_url'], $uploadResult['duration'] ?? 0, $videoUrl, $lessonId]
|
||||
);
|
||||
} else {
|
||||
$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', ?)",
|
||||
[$courseId, $title, $uploadResult['video_uuid'], $uploadResult['local_path'], $uploadResult['hls_url'], $uploadResult['thumbnail_url'], $uploadResult['duration'] ?? 0, $videoUrl]
|
||||
);
|
||||
}
|
||||
|
||||
// 3. Trigger Autonomous Zero-Touch AI Analysis & Socratic Checkpoint Generation
|
||||
\App\Services\AiVideoAnalyzerService::processLessonAutonomously($lessonId);
|
||||
|
||||
@@ -211,6 +211,25 @@ class CurriculumService
|
||||
return $walk(self::getCurriculumTree());
|
||||
}
|
||||
|
||||
/** Resolve a manifest file path to its canonical lesson record. */
|
||||
public static function findLessonByFile(string $file): ?array
|
||||
{
|
||||
$walk = function ($node) use (&$walk, $file): ?array {
|
||||
if (!is_array($node)) return null;
|
||||
if (isset($node['lessons']) && is_array($node['lessons'])) {
|
||||
foreach ($node['lessons'] as $lesson) {
|
||||
if (is_array($lesson) && (string)($lesson['file'] ?? '') === $file) return $lesson;
|
||||
}
|
||||
}
|
||||
foreach ($node as $value) {
|
||||
$found = $walk($value);
|
||||
if ($found !== null) return $found;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
return $walk(self::getCurriculumTree());
|
||||
}
|
||||
|
||||
/**
|
||||
* Save/Update Complete Curriculum Tree Manifest
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user