Files
saqel/backend/scripts/sync_curriculum_to_database.php
T

158 lines
8.4 KiB
PHP

<?php
// Use the same environment loader and PSR-4 bootstrap as the web API.
// Running this script directly must still load backend/.env.
require_once __DIR__ . '/../app/bootstrap.php';
use App\Core\Database;
use App\Services\CurriculumService;
echo "=== SAQEL ENTERPRISE CURRICULUM DATABASE SYNC ===\n";
$manifestFile = __DIR__ . '/../storage/curriculum/manifest.json';
if (!file_exists($manifestFile)) {
die("Error: manifest.json not found at $manifestFile\n");
}
$manifest = json_decode(file_get_contents($manifestFile), true);
if (!$manifest) {
die("Error: Failed to parse manifest.json\n");
}
// 1. Ensure Default Admin/Official Teacher exists for curriculum courses
$teacher = Database::selectOne("SELECT id, uuid FROM teachers LIMIT 1");
if (!$teacher) {
echo "Creating Default Official Curriculum Teacher...\n";
$identUuid = 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));
$identId = Database::insert(
"INSERT INTO auth_identities (uuid, phone_number, phone_hash, status) VALUES (?, ?, ?, 'active')",
[$identUuid, \App\Core\Security::encrypt('962790000000'), \App\Core\Security::blindIndex('962790000000')]
);
$teachUuid = 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));
$teacherId = Database::insert(
"INSERT INTO teachers (uuid, identity_id, full_name, specialization, bio) VALUES (?, ?, 'فريق صَقِل للمناهج الرسمية', 'المناهج الوزارية المطورة', 'الجهة الرسمية لإعداد وفهرسة المناهج الوزارية المطورة لوزارة التربية والتعليم')",
[$teachUuid, $identId]
);
$teacher = ['id' => $teacherId, 'uuid' => $teachUuid];
}
$teacherId = (int)$teacher['id'];
// 2. Iterate through Grades and Subjects in manifest
foreach ($manifest as $gradeKey => $grade) {
$gradeName = $grade['name'] ?? $gradeKey;
foreach ($grade['subjects'] as $subjectKey => $subjectData) {
$subjectName = $subjectData['name'] ?? $subjectKey;
$stream = 'scientific';
if (str_contains($subjectKey, 'english')) {
$stream = 'common';
}
// A. Insert/Update Subject
$dbSubject = Database::selectOne("SELECT id FROM subjects WHERE code = ? LIMIT 1", [$subjectKey]);
if (!$dbSubject) {
$subId = Database::insert(
"INSERT INTO subjects (name, code, stream, is_active) VALUES (?, ?, ?, 1)",
[$subjectName, $subjectKey, $stream]
);
echo "✅ Created Subject: {$subjectName} (code: {$subjectKey})\n";
} else {
$subId = (int)$dbSubject['id'];
Database::query("UPDATE subjects SET name = ? WHERE id = ?", [$subjectName, $subId]);
}
// B. Insert/Update Courses for each Semester
foreach ($subjectData['semesters'] as $semesterKey => $semesterData) {
$semType = ($semesterKey === 'semester_2') ? 'second' : 'first';
$courseTitle = "{$subjectName} — {$gradeName} (" . ($semType === 'first' ? 'الفصل الأول' : 'الفصل الثاني') . ")";
$dbCourse = Database::selectOne("SELECT id FROM courses WHERE subject_id = ? AND semester = ? LIMIT 1", [$subId, $semType]);
if (!$dbCourse) {
$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));
$courseId = Database::insert(
"INSERT INTO courses (uuid, subject_id, teacher_id, title, description, semester, price_jod, is_published)
VALUES (?, ?, ?, ?, ?, ?, 0.00, 1)",
[$cUuid, $subId, $teacherId, $courseTitle, "المساق الوزاري الرسمي المعتمد والمفرغ تفاعلياً لمنهاج {$subjectName}", $semType]
);
echo " 📚 Created Course: {$courseTitle} (ID: {$courseId})\n";
} else {
$courseId = (int)$dbCourse['id'];
Database::query("UPDATE courses SET title = ? WHERE id = ?", [$courseTitle, $courseId]);
}
// C. Insert/Update Lessons under each Unit
$seqOrder = 1;
foreach ($semesterData['units'] as $unitKey => $unitData) {
$unitName = $unitData['name'] ?? $unitKey;
foreach ($unitData['lessons'] as $les) {
$lessonTitle = $les['title'];
$filePath = $les['file'];
$fullDiskPath = __DIR__ . '/../storage/curriculum/' . $filePath;
$mdContent = '';
if (file_exists($fullDiskPath)) {
$mdContent = file_get_contents($fullDiskPath);
}
$aiVideoUrl = $les['ai_video_url'] ?? null;
$cheatSheet = $les['cheat_sheet'] ?? null;
$socraticQuiz = isset($les['socratic_quiz']) ? json_encode($les['socratic_quiz'], JSON_UNESCAPED_UNICODE) : null;
// Match existing lesson by course_id and title or file path
$dbLesson = Database::selectOne(
"SELECT id FROM lessons WHERE course_id = ? AND title = ? LIMIT 1",
[$courseId, $lessonTitle]
);
if (!$dbLesson) {
$lesId = Database::insert(
"INSERT INTO lessons (course_id, title, sequence_order, ai_video_url, markdown_content, cheat_sheet_markdown, socratic_quiz_json, is_free_preview)
VALUES (?, ?, ?, ?, ?, ?, ?, 1)",
[$courseId, $lessonTitle, $seqOrder, $aiVideoUrl, $mdContent, $cheatSheet, $socraticQuiz]
);
echo " 📄 [NEW] Lesson inserted: {$lessonTitle} (ID: {$lesId})\n";
} else {
$lesId = (int)$dbLesson['id'];
Database::query(
"UPDATE lessons SET sequence_order = ?, markdown_content = ?, ai_video_url = COALESCE(?, ai_video_url), cheat_sheet_markdown = COALESCE(?, cheat_sheet_markdown), socratic_quiz_json = COALESCE(?, socratic_quiz_json) WHERE id = ?",
[$seqOrder, $mdContent, $aiVideoUrl, $cheatSheet, $socraticQuiz, $lesId]
);
echo " 🔄 [UPDATED] Lesson: {$lessonTitle} (ID: {$lesId})\n";
}
$seqOrder++;
}
}
// D. Insert Resources (Books, Activity Books)
if (!empty($semesterData['resources'])) {
foreach ($semesterData['resources'] as $resGroupKey => $resGroup) {
foreach ($resGroup['items'] as $resItem) {
$resTitle = $resItem['title'];
$resFilePath = $resItem['file'];
$resDiskPath = __DIR__ . '/../storage/curriculum/' . $resFilePath;
$resMd = file_exists($resDiskPath) ? file_get_contents($resDiskPath) : '';
// Add as special lesson / resource entry
$dbResLesson = Database::selectOne(
"SELECT id FROM lessons WHERE course_id = ? AND title = ? LIMIT 1",
[$courseId, $resTitle]
);
if (!$dbResLesson) {
Database::insert(
"INSERT INTO lessons (course_id, title, sequence_order, markdown_content, is_free_preview)
VALUES (?, ?, ?, ?, 1)",
[$courseId, $resTitle, $seqOrder, $resMd]
);
echo " 📎 [RESOURCE] Added Resource: {$resTitle}\n";
}
$seqOrder++;
}
}
}
}
}
}
echo "\n🎉 SUCCESS! All curriculum subjects, courses, and lessons are synchronized with MySQL database!\n";