feat: Implement semantic video naming, MySQL database curriculum synchronization, and live two-way binding between filesystem and DB

This commit is contained in:
Hamza-Ayed
2026-08-29 05:40:45 +03:00
parent 9fc60b2cf5
commit 22568fe220
2 changed files with 196 additions and 8 deletions
@@ -190,11 +190,28 @@ class CurriculumController
CurriculumService::saveLessonAiAssets($file, $aiAssets);
}
// Sync to MySQL Database Table `lessons` if connected
try {
$aiVideoUrl = $aiAssets['ai_video_url'] ?? null;
$cheatSheet = $aiAssets['cheat_sheet'] ?? null;
$socraticJson = isset($aiAssets['socratic_quiz']) ? json_encode($aiAssets['socratic_quiz'], JSON_UNESCAPED_UNICODE) : null;
// Search lesson by matching filename or title
$filename = basename($file, '.md');
\App\Core\Database::query(
"UPDATE lessons SET markdown_content = ?, ai_video_url = COALESCE(?, ai_video_url), cheat_sheet_markdown = COALESCE(?, cheat_sheet_markdown), socratic_quiz_json = COALESCE(?, socratic_quiz_json)
WHERE title LIKE ? OR markdown_content LIKE ?",
[$content, $aiVideoUrl, $cheatSheet, $socraticJson, "%{$filename}%", "%{$file}%"]
);
} catch (\Throwable $dbEx) {
error_log("Curriculum DB save sync note: " . $dbEx->getMessage());
}
$serverFullPath = realpath(__DIR__ . '/../../storage/curriculum') . '/' . ltrim($file, '/');
$response->json([
'status' => 'success',
'message' => 'تم حفظ واعتماد محتوى الدرس في المنهاج بنجاح!',
'message' => 'تم حفظ واعتماد محتوى الدرس في المنهاج وقاعدة البيانات بنجاح!',
'server_full_path' => $serverFullPath
]);
}
@@ -217,8 +234,6 @@ class CurriculumController
// Generate Assets
require_once __DIR__ . '/../Services/AiLessonEnhancerService.php';
// We will adapt the service call here since AiLessonEnhancerService expects lessonId.
// Actually, let's create a custom static method in AiLessonEnhancerService to accept raw text.
$assets = \App\Services\AiLessonEnhancerService::generateFromText('الدرس', $content);
if ($assets) {
@@ -230,7 +245,7 @@ class CurriculumController
}
/**
* Direct Video Upload to Platform Storage
* Direct Video Upload to Platform Storage with Semantic Lesson Binding
*/
public function uploadLessonVideo(Request $request, Response $response): void
{
@@ -252,7 +267,11 @@ class CurriculumController
$videoTmp = $_FILES['video_file']['tmp_name'];
$ext = strtolower(pathinfo($_FILES['video_file']['name'], PATHINFO_EXTENSION)) ?: 'mp4';
$safeName = 'video_' . md5($file) . '_' . time() . '.' . $ext;
// Semantic, human-readable file naming (e.g. video_grade_10_math_10_unit_01_lesson_01.mp4)
$cleanBase = preg_replace('/[^a-zA-Z0-9_-]+/', '_', str_replace(['.md', '/'], ['', '_'], $file));
$cleanBase = trim($cleanBase, '_');
$safeName = 'video_' . $cleanBase . '_' . time() . '.' . $ext;
$destPath = $uploadDir . '/' . $safeName;
if (!move_uploaded_file($videoTmp, $destPath)) {
@@ -262,15 +281,27 @@ class CurriculumController
$videoUrl = '/uploads/curriculum_videos/' . $safeName;
// Automatically update AI assets with the new video URL
// 1. Update Lesson AI assets in manifest.json & filesystem
$currentAssets = CurriculumService::getLessonAiAssets($file);
$currentAssets['ai_video_url'] = $videoUrl;
CurriculumService::saveLessonAiAssets($file, $currentAssets);
// 2. Direct Sync to MySQL Database Table `lessons`
try {
$filename = basename($file, '.md');
\App\Core\Database::query(
"UPDATE lessons SET ai_video_url = ? WHERE title LIKE ? OR markdown_content LIKE ?",
[$videoUrl, "%{$filename}%", "%{$file}%"]
);
} catch (\Throwable $dbEx) {
error_log("Video DB sync note: " . $dbEx->getMessage());
}
$response->json([
'status' => 'success',
'message' => 'تم رفع وتثبيت فيديو الشرح على منصة صَقِل بنجاح!',
'video_url' => $videoUrl
'message' => 'تم رفع وتثبيت فيديو الشرح وربطه بالدرس وقاعدة البيانات بنجاح!',
'video_url' => $videoUrl,
'file_name' => $safeName
]);
}
}