Update Saqel Platform: 2026-08-29 22:41:36

This commit is contained in:
Hamza-Ayed
2026-08-29 22:41:36 +03:00
parent 051b9322f6
commit c4c59bc828
5 changed files with 250 additions and 14 deletions
+150 -1
View File
@@ -16,7 +16,156 @@ class CurriculumService
*/
public static function ensureSchema(): void
{
// No-op
// No-op (schema managed via database_schema.sql)
}
/**
* Runtime migration: add is_system_curriculum (and related columns) to `courses`
* if they are missing. Safe to call multiple times — uses IF NOT EXISTS / IGNORE.
*/
public static function ensureSystemCurriculumColumn(): void
{
static $ran = false;
if ($ran) return;
$ran = true;
try {
// Check whether the column exists to avoid noisy ALTER errors on every request
$row = Database::selectOne(
"SELECT COUNT(*) as cnt FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'courses'
AND COLUMN_NAME = 'is_system_curriculum'
LIMIT 1"
);
if (empty($row['cnt'])) {
Database::query(
"ALTER TABLE `courses`
ADD COLUMN `is_system_curriculum` TINYINT(1) NOT NULL DEFAULT 0
COMMENT 'الدورة الرئيسية للمنهاج الوزاري'
AFTER `is_school_exclusive`"
);
}
// Also ensure grade_level + stream columns exist (for student filtering)
$gradeRow = Database::selectOne(
"SELECT COUNT(*) as cnt FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'courses'
AND COLUMN_NAME = 'grade_level'
LIMIT 1"
);
if (empty($gradeRow['cnt'])) {
Database::query(
"ALTER TABLE `courses`
ADD COLUMN `grade_level` VARCHAR(50) DEFAULT NULL
COMMENT 'المرحلة الدراسية مثل: tawjihi_2008'
AFTER `is_system_curriculum`,
ADD COLUMN `stream` ENUM('scientific','literary','vocational','general') DEFAULT NULL
COMMENT 'الفرع الدراسي'
AFTER `grade_level`"
);
}
} catch (\Throwable $e) {
error_log('[CurriculumService] ensureSystemCurriculumColumn error: ' . $e->getMessage());
}
}
/**
* Resolve or create the master system curriculum course.
*
* Returns a guaranteed valid `course_id` that satisfies the FK constraint on
* `lessons.course_id → courses.id`. Called by CurriculumController when
* uploading AI/ministry videos without an explicit teacher course.
*
* @return int Valid course_id
* @throws \RuntimeException if no subjects or teachers exist and creation fails
*/
public static function getOrCreateSystemCourse(): int
{
// Ensure the column exists before querying it (runtime migration)
self::ensureSystemCurriculumColumn();
// 1. Look for existing master system course
$existing = Database::selectOne(
"SELECT id FROM courses WHERE is_system_curriculum = 1 LIMIT 1"
);
if ($existing && !empty($existing['id'])) {
return (int)$existing['id'];
}
// 2. Also try by canonical title in case migration was run after records existed
$byTitle = Database::selectOne(
"SELECT id FROM courses WHERE title LIKE '%منهاج وزارة التربية%' LIMIT 1"
);
if ($byTitle && !empty($byTitle['id'])) {
// Stamp it so future lookups are fast
Database::query(
"UPDATE courses SET is_system_curriculum = 1 WHERE id = ?",
[(int)$byTitle['id']]
);
return (int)$byTitle['id'];
}
// 3. Create a new master course — resolve required FK dependencies first
// Resolve subject_id (use first available subject or create a placeholder)
$subject = Database::selectOne("SELECT id FROM subjects LIMIT 1");
if (!$subject) {
$subjectId = Database::insert(
"INSERT INTO subjects (name, description) VALUES ('المنهاج الوزاري الأردني', 'مقررات وزارة التربية والتعليم المعتمدة') ON DUPLICATE KEY UPDATE id = LAST_INSERT_ID(id)"
);
} else {
$subjectId = (int)$subject['id'];
}
// Resolve teacher_id (use system teacher with id=1 or first available)
$teacher = Database::selectOne("SELECT id FROM teachers WHERE id = 1 LIMIT 1");
if (!$teacher) {
$teacher = Database::selectOne("SELECT id FROM teachers LIMIT 1");
}
if (!$teacher) {
// Last resort: look up the super_admin user and create a teacher row for them
$adminUser = Database::selectOne(
"SELECT id FROM users WHERE role = 'super_admin' LIMIT 1"
);
$adminUserId = $adminUser ? (int)$adminUser['id'] : 1;
$teacherId = Database::insert(
"INSERT INTO teachers (user_id, specialization, verification_status)
VALUES (?, 'المنهاج الوزاري', 'verified')
ON DUPLICATE KEY UPDATE id = LAST_INSERT_ID(id)",
[$adminUserId]
);
} else {
$teacherId = (int)$teacher['id'];
}
// Generate stable UUID for the master course
$uuid = 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, is_system_curriculum, grade_level, stream)
VALUES
(?, ?, ?, 'منهاج وزارة التربية والتعليم الأساسي',
'الدورة الرئيسية للمنهاج الوزاري — تُستخدم لرفع وتنظيم فيديوهات الذكاء الاصطناعي التعليمية',
'full_year', 0.00, 1, 1, 'tawjihi_2008', 'scientific')",
[$uuid, $subjectId, $teacherId]
);
if (!$courseId) {
throw new \RuntimeException('فشل إنشاء الدورة الرئيسية للمنهاج — تحقق من وجود records في جداول subjects و teachers');
}
error_log("[CurriculumService] Created master system course id={$courseId}");
return (int)$courseId;
}
private static string $storagePath = __DIR__ . '/../../storage/curriculum';