+
= h(t('Admin', 'الإدارة')) ?>
@@ -296,6 +307,7 @@ render_head(
+
@@ -378,6 +390,8 @@ render_head(
+
+
diff --git a/admin_assignments.php b/admin_assignments.php
index 24caf92..781f21e 100644
--- a/admin_assignments.php
+++ b/admin_assignments.php
@@ -1,6 +1,9 @@
exec("CREATE TABLE IF NOT EXISTS teacher_assignments (
@@ -20,6 +23,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$post_id = (int)($_POST['id'] ?? $id);
if ($post_action === 'delete' && $post_id > 0) {
+ require_permission('assignments', 'delete');
$stmt = db()->prepare("DELETE FROM teacher_assignments WHERE id = ?");
$stmt->execute([$post_id]);
header('Location: ' . app_url('admin.php', ['page' => 'assignments']));
@@ -95,7 +99,9 @@ $items = $stmt->fetchAll(PDO::FETCH_ASSOC);
+
+
= h(t('Teacher Assignments', 'تعيينات المعلمين')) ?>
diff --git a/admin_classes.php b/admin_classes.php
index 8bebf24..106ea98 100644
--- a/admin_classes.php
+++ b/admin_classes.php
@@ -1,6 +1,9 @@
0) {
+ require_permission('classes', 'delete');
$stmt = db()->prepare("DELETE FROM classes WHERE id = ?");
$stmt->execute([$post_id]);
header('Location: ' . app_url('admin.php', ['page' => 'classes']));
@@ -19,6 +23,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
}
if ($post_action === 'edit' || $post_action === 'add') {
+ require_permission('classes', $post_action === 'add' ? 'add' : 'edit');
$name_en = $_POST['name_en'] ?? '';
$name_ar = $_POST['name_ar'] ?? '';
$desc_en = $_POST['description_en'] ?? '';
@@ -64,7 +69,9 @@ $items = $stmt->fetchAll(PDO::FETCH_ASSOC);
+
+
= h(t('Classes', 'الصفوف')) ?>
@@ -108,12 +115,16 @@ $items = $stmt->fetchAll(PDO::FETCH_ASSOC);
= h(current_lang() === 'ar' ? $row['description_ar'] : $row['description_en']) ?>
+
+
+
+
diff --git a/admin_courses.php b/admin_courses.php
index 1028cf5..3809899 100644
--- a/admin_courses.php
+++ b/admin_courses.php
@@ -1,6 +1,9 @@
0) {
+ require_permission('courses', 'delete');
$stmt = db()->prepare("DELETE FROM courses WHERE id = ?");
$stmt->execute([$post_id]);
header('Location: ' . app_url('admin.php', ['page' => 'courses']));
@@ -33,6 +37,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
}
if ($post_action === 'edit' || $post_action === 'add') {
+ require_permission('courses', $post_action === 'add' ? 'add' : 'edit');
$name_en = $_POST['name_en'] ?? '';
$name_ar = $_POST['name_ar'] ?? '';
$desc_en = $_POST['description_en'] ?? '';
@@ -124,7 +129,8 @@ $items = $stmt->fetchAll(PDO::FETCH_ASSOC);
= h(t('Courses', 'الدورات')) ?>
-
@@ -216,12 +222,15 @@ $items = $stmt->fetchAll(PDO::FETCH_ASSOC);
+
+
+
diff --git a/admin_plans.php b/admin_plans.php
index e9ee24d..5b2cf71 100644
--- a/admin_plans.php
+++ b/admin_plans.php
@@ -1,6 +1,9 @@
0) {
+ require_permission('plans', 'delete');
$stmt = db()->prepare("DELETE FROM plans WHERE id = ?");
$stmt->execute([$post_id]);
header('Location: ' . app_url('admin.php', ['page' => 'plans']));
@@ -17,6 +21,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
}
if ($post_action === 'edit' || $post_action === 'add') {
+ require_permission('plans', $post_action === 'add' ? 'add' : 'edit');
$plan_key = $_POST['plan_key'] ?? '';
$name_en = $_POST['name_en'] ?? '';
$name_ar = $_POST['name_ar'] ?? '';
@@ -121,12 +126,16 @@ $items = $stmt->fetchAll(PDO::FETCH_ASSOC);
= h(format_price((float)$row['price_yearly'])) ?>
= h((string)$row['subjects_limit']) ?>
+
+
+
+
diff --git a/admin_roles.php b/admin_roles.php
new file mode 100644
index 0000000..81c3387
--- /dev/null
+++ b/admin_roles.php
@@ -0,0 +1,258 @@
+ t('Dashboard', 'لوحة التحكم'),
+ 'classes' => t('Classes', 'الصفوف'),
+ 'subjects' => t('Subjects', 'المواد'),
+ 'teachers' => t('Teachers', 'المعلمين'),
+ 'courses' => t('Courses', 'الدورات'),
+ 'assignments' => t('Assignments', 'الواجبات'),
+ 'students' => t('Students', 'الطلاب'),
+ 'plans' => t('Plans', 'الخطط'),
+ 'users' => t('Platform Users', 'مستخدمي المنصة'),
+ 'roles' => t('Role Groups', 'مجموعات الصلاحيات'),
+ 'integrations' => t('Integrations', 'عمليات الربط'),
+ 'landing' => t('Landing Page', 'الصفحة الرئيسية'),
+];
+
+$action = $_GET['action'] ?? 'list';
+$id = (int)($_GET['id'] ?? 0);
+
+if ($_SERVER['REQUEST_METHOD'] === 'POST') {
+ $post_action = $_POST['action'] ?? $action;
+ $post_id = (int)($_POST['id'] ?? $id);
+
+ if ($post_action === 'delete' && $post_id > 0) {
+ require_permission('roles', 'delete');
+ // check if system role
+ $stmt = db()->prepare("SELECT is_system FROM roles WHERE id = ?");
+ $stmt->execute([$post_id]);
+ $role = $stmt->fetch(PDO::FETCH_ASSOC);
+ if ($role && !$role['is_system']) {
+ $stmt = db()->prepare("DELETE FROM roles WHERE id = ?");
+ $stmt->execute([$post_id]);
+ }
+ header('Location: ' . app_url('admin.php', ['page' => 'roles']));
+ exit;
+ }
+
+ if ($post_action === 'edit' || $post_action === 'add') {
+ require_permission('roles', $post_action === 'add' ? 'add' : 'edit');
+ $name = trim($_POST['name'] ?? '');
+ $description = trim($_POST['description'] ?? '');
+ $perms = $_POST['perms'] ?? []; // e.g. ['classes' => ['view'=>1, 'add'=>1]]
+
+ if ($post_action === 'edit' && $post_id > 0) {
+ $stmt = db()->prepare("UPDATE roles SET name=?, description=? WHERE id=?");
+ $stmt->execute([$name, $description, $post_id]);
+ $role_id = $post_id;
+ } else {
+ $stmt = db()->prepare("INSERT INTO roles (name, description) VALUES (?, ?)");
+ $stmt->execute([$name, $description]);
+ $role_id = db()->lastInsertId();
+ }
+
+ // update permissions
+ if ($role_id) {
+ $stmt = db()->prepare("DELETE FROM role_permissions WHERE role_id = ?");
+ $stmt->execute([$role_id]);
+
+ $stmt = db()->prepare("INSERT INTO role_permissions (role_id, page, can_view, can_add, can_edit, can_delete) VALUES (?, ?, ?, ?, ?, ?)");
+ foreach ($pages as $p => $pname) {
+ if (isset($perms[$p])) {
+ $v = !empty($perms[$p]['view']) ? 1 : 0;
+ $a = !empty($perms[$p]['add']) ? 1 : 0;
+ $e = !empty($perms[$p]['edit']) ? 1 : 0;
+ $d = !empty($perms[$p]['delete']) ? 1 : 0;
+ if ($v || $a || $e || $d) {
+ $stmt->execute([$role_id, $p, $v, $a, $e, $d]);
+ }
+ }
+ }
+ }
+ header('Location: ' . app_url('admin.php', ['page' => 'roles']));
+ exit;
+ }
+}
+
+$roles = db()->query("SELECT * FROM roles ORDER BY id DESC")->fetchAll(PDO::FETCH_ASSOC);
+
+// Fetch permissions for all roles
+$stmt = db()->query("SELECT * FROM role_permissions");
+$all_perms = $stmt->fetchAll(PDO::FETCH_ASSOC);
+$role_perms = [];
+foreach ($all_perms as $p) {
+ $role_perms[$p['role_id']][$p['page']] = $p;
+}
+
+// Merge permissions into roles for JS
+foreach ($roles as &$r) {
+ $r['permissions'] = $role_perms[$r['id']] ?? [];
+}
+unset($r);
+
+?>
+
+
+
+
+
diff --git a/admin_subjects.php b/admin_subjects.php
index f6d4a0e..22267c8 100644
--- a/admin_subjects.php
+++ b/admin_subjects.php
@@ -1,6 +1,9 @@
0) {
+ require_permission('subjects', 'delete');
$stmt = db()->prepare("DELETE FROM subjects WHERE id = ?");
$stmt->execute([$post_id]);
header('Location: ' . app_url('admin.php', ['page' => 'subjects']));
@@ -21,6 +25,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
}
if ($post_action === 'edit' || $post_action === 'add') {
+ require_permission('subjects', $post_action === 'add' ? 'add' : 'edit');
$class_id = !empty($_POST['class_id']) ? (int)$_POST['class_id'] : null;
$title_en = $_POST['title_en'] ?? '';
$title_ar = $_POST['title_ar'] ?? '';
@@ -89,7 +94,9 @@ $items = $stmt->fetchAll(PDO::FETCH_ASSOC);
+
+
+
+
+
+
+
+
+
+= h(t('Role Groups', 'مجموعات الصلاحيات')) ?>
+= h(t('Manage roles and their page permissions.', 'إدارة الأدوار وصلاحيات الصفحات الخاصة بها.')) ?>
+
+
+
+
+
+
+
+
+
+| = h(t('Role Name', 'اسم الدور')) ?> | += h(t('Description', 'الوصف')) ?> | += h(t('Actions', 'الإجراءات')) ?> | +
|---|---|---|
| + = h($r['name']) ?> + + = h(t('System', 'نظام')) ?> + + | += h($r['description']) ?> | +
+
+
+
+
+
+
+
+
+
+ |
+
| = h(t('No roles found.', 'لا توجد أدوار.')) ?> | ||
+
+
+
diff --git a/admin_students.php b/admin_students.php
index a5d1992..8dd46b3 100644
--- a/admin_students.php
+++ b/admin_students.php
@@ -1,6 +1,9 @@
0) {
+ require_permission('students', 'delete');
$stmt = db()->prepare("DELETE FROM student_subscriptions WHERE id = ?");
$stmt->execute([$post_id]);
header('Location: ' . app_url('admin.php', ['page' => 'students']));
@@ -17,6 +21,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
}
if ($post_action === 'edit' || $post_action === 'add') {
+ require_permission('students', $post_action === 'add' ? 'add' : 'edit');
$full_name = $_POST['full_name'] ?? '';
$email = $_POST['email'] ?? '';
$whatsapp = $_POST['whatsapp'] ?? '';
@@ -140,14 +145,18 @@ $items = $stmt->fetchAll(PDO::FETCH_ASSOC);
+
+
+= h(t('Subjects', 'المواد')) ?>
@@ -149,12 +156,16 @@ $items = $stmt->fetchAll(PDO::FETCH_ASSOC);
+
+
+
+
diff --git a/admin_teachers.php b/admin_teachers.php
index 10cf875..3fcb1e6 100644
--- a/admin_teachers.php
+++ b/admin_teachers.php
@@ -1,6 +1,9 @@
0) {
+ require_permission('teachers', 'delete');
$stmt = db()->prepare("DELETE FROM teachers WHERE id = ?");
$stmt->execute([$post_id]);
header('Location: ' . app_url('admin.php', ['page' => 'teachers']));
@@ -17,6 +21,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
}
if ($post_action === 'edit' || $post_action === 'add') {
+ require_permission('teachers', $post_action === 'add' ? 'add' : 'edit');
$name = $_POST['name'] ?? '';
$email = $_POST['email'] ?? '';
$phone = $_POST['phone'] ?? '';
@@ -100,7 +105,9 @@ $items = $stmt->fetchAll(PDO::FETCH_ASSOC);
+
+
= h(t('Teachers', 'المعلمون')) ?>
@@ -153,14 +160,18 @@ $items = $stmt->fetchAll(PDO::FETCH_ASSOC);
+
+
+
+
diff --git a/admin_users.php b/admin_users.php
index e2231d5..c58be91 100644
--- a/admin_users.php
+++ b/admin_users.php
@@ -1,11 +1,11 @@
0) {
+ require_permission('users', 'delete');
// Prevent deleting oneself
if ($post_id !== (int)$_SESSION['user_id']) {
$stmt = db()->prepare("DELETE FROM users WHERE id = ?");
@@ -25,6 +26,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
}
if ($post_action === 'edit' || $post_action === 'add') {
+ require_permission('users', $post_action === 'add' ? 'add' : 'edit');
$name = trim($_POST['name'] ?? '');
$email = trim($_POST['email'] ?? '');
$phone = trim($_POST['phone'] ?? '');
@@ -32,6 +34,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!in_array($role, ['admin', 'user'])) {
$role = 'user';
}
+ $role_id = $_POST['role_id'] ?? '';
+ if ($role_id === '') $role_id = null;
$raw_password = $_POST['password'] ?? '';
$profile_picture = '';
@@ -71,11 +75,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
}
if ($post_action === 'edit' && $post_id > 0) {
- $stmt = db()->prepare("UPDATE users SET name=?, email=?, phone=?, role=?, profile_picture=?, password=? WHERE id=?");
- $stmt->execute([$name, $email, $phone, $role, $profile_picture, $final_password, $post_id]);
+ $stmt = db()->prepare("UPDATE users SET name=?, email=?, phone=?, role=?, profile_picture=?, password=?, role_id=? WHERE id=?");
+ $stmt->execute([$name, $email, $phone, $role, $profile_picture, $final_password, $role_id, $post_id]);
} else {
- $stmt = db()->prepare("INSERT INTO users (name, email, phone, role, profile_picture, password) VALUES (?, ?, ?, ?, ?, ?)");
- $stmt->execute([$name, $email, $phone, $role, $profile_picture, $final_password]);
+ $stmt = db()->prepare("INSERT INTO users (name, email, phone, role, profile_picture, password, role_id) VALUES (?, ?, ?, ?, ?, ?, ?)");
+ $stmt->execute([$name, $email, $phone, $role, $profile_picture, $final_password, $role_id]);
}
header('Location: ' . app_url('admin.php', ['page' => 'users']));
exit;
@@ -90,17 +94,17 @@ $offset = ($page_num - 1) * $limit;
$where = "1=1";
$params = [];
if ($search) {
- $where .= " AND (name LIKE ? OR email LIKE ?)";
+ $where .= " AND (u.name LIKE ? OR u.email LIKE ?)";
$params[] = "%$search%";
$params[] = "%$search%";
}
-$stmt = db()->prepare("SELECT COUNT(*) FROM users WHERE $where");
+$stmt = db()->prepare("SELECT COUNT(*) FROM users u WHERE $where");
$stmt->execute($params);
$total = $stmt->fetchColumn();
$total_pages = ceil($total / $limit);
-$stmt = db()->prepare("SELECT * FROM users WHERE $where ORDER BY id DESC LIMIT ? OFFSET ?");
+$stmt = db()->prepare("SELECT u.*, r.name as role_name FROM users u LEFT JOIN roles r ON u.role_id = r.id WHERE $where ORDER BY u.id DESC LIMIT ? OFFSET ?");
$params[] = $limit;
$params[] = $offset;
foreach($params as $k => $v) {
@@ -109,15 +113,20 @@ foreach($params as $k => $v) {
$stmt->execute();
$users = $stmt->fetchAll(PDO::FETCH_ASSOC);
+$stmt = db()->query("SELECT id, name FROM roles ORDER BY name ASC");
+$roles_list = $stmt->fetchAll(PDO::FETCH_ASSOC);
+
?>
+
+
= h($row['phone']) ?>
= h(t('Platform Users', 'مستخدمي المنصة')) ?>
= h(t('Manage administrators and staff.', 'إدارة المسؤولين والموظفين.')) ?>
@@ -139,7 +148,7 @@ $users = $stmt->fetchAll(PDO::FETCH_ASSOC);
= h(t('Name', 'الاسم')) ?>
= h(t('Email', 'البريد الإلكتروني')) ?>
= h(t('Phone', 'الهاتف')) ?>
- = h(t('Role', 'الدور')) ?>
+ = h(t('Role Group', 'الصلاحيات')) ?>
= h(t('Actions', 'الإجراءات')) ?>
@@ -163,7 +172,9 @@ $users = $stmt->fetchAll(PDO::FETCH_ASSOC);
= h($u['email']) ?>
= h($u['phone']) ?>
-
+
+ = h($u['role_name']) ?>
+
= h(t('Admin', 'مسؤول')) ?>
= h(t('User', 'مستخدم')) ?>
@@ -171,10 +182,13 @@ $users = $stmt->fetchAll(PDO::FETCH_ASSOC);
+
-
+
+
+
-
+
+
+
+