39496-vm/admin_roles.php
2026-04-08 08:11:15 +00:00

270 lines
14 KiB
PHP

<?php
// admin_roles.php
require_once __DIR__ . '/includes/app.php';
require_once __DIR__ . '/includes/auth.php';
try {
db()->query('SELECT 1 FROM roles LIMIT 1');
} catch (Exception $e) {
ob_start();
require_once __DIR__ . '/db/migrations/migrate_roles.php';
ob_end_clean();
header('Location: ' . app_url('admin.php', ['page' => 'roles']));
exit;
}
require_permission('roles', 'view');
$pages = [
'dashboard' => 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', 'الصفحة الرئيسية'),
'profile' => t('Platform Profile', 'ملف المنصة'),
];
$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);
?>
<div class="section-header mb-4 d-flex justify-content-between align-items-center">
<div>
<h1 class="section-title mb-2"><?= h(t('Role Groups', 'مجموعات الصلاحيات')) ?></h1>
<p class="text-secondary mb-0"><?= h(t('Manage roles and their page permissions.', 'إدارة الأدوار وصلاحيات الصفحات الخاصة بها.')) ?></p>
</div>
<?php if (has_permission('roles', 'add')): ?>
<button class="btn btn-dark" data-bs-toggle="modal" data-bs-target="#roleModal" onclick="editRole(null)">
<?= h(t('Add Role Group', 'إضافة مجموعة صلاحيات')) ?>
</button>
<?php endif; ?>
</div>
<div class="panel-card p-0 overflow-hidden">
<div class="table-responsive">
<table class="table table-hover align-middle mb-0">
<thead class="bg-light">
<tr>
<th class="px-4 py-3"><?= h(t('Role Name', 'اسم الدور')) ?></th>
<th class="py-3"><?= h(t('Description', 'الوصف')) ?></th>
<th class="px-4 py-3 text-end"><?= h(t('Actions', 'الإجراءات')) ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($roles as $r): ?>
<tr>
<td class="px-4 py-3 fw-bold text-dark">
<?= h($r['name']) ?>
<?php if ($r['is_system']): ?>
<span class="badge bg-secondary ms-2"><?= h(t('System', 'نظام')) ?></span>
<?php endif; ?>
</td>
<td class="py-3 text-secondary"><?= h($r['description']) ?></td>
<td class="px-4 py-3 text-end">
<div class="btn-group btn-group-sm">
<?php if (has_permission('roles', 'edit')): ?>
<button class="btn btn-outline-dark" onclick='editRole(<?= htmlspecialchars(json_encode($r), ENT_QUOTES) ?>)' data-bs-toggle="modal" data-bs-target="#roleModal">
<svg width="16" height="16" fill="currentColor" class="me-1" viewBox="0 0 16 16"><path d="M12.146.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1 0 .708l-10 10a.5.5 0 0 1-.168.11l-5 2a.5.5 0 0 1-.65-.65l2-5a.5.5 0 0 1 .11-.168l10-10zM11.207 2.5 13.5 4.793 14.793 3.5 12.5 1.207 11.207 2.5zm1.586 3L10.5 3.207 4 9.707V10h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.293l6.5-6.5zm-9.761 5.175-.106.106-1.528 3.821 3.821-1.528.106-.106A.5.5 0 0 1 5 12.5V12h-.5a.5.5 0 0 1-.5-.5V11h-.5a.5.5 0 0 1-.468-.325z"/></svg><?= h(t($r['is_system'] ? 'View' : 'Edit', $r['is_system'] ? 'عرض' : 'تعديل')) ?>
</button>
<?php endif; ?>
<?php if (!$r['is_system'] && has_permission('roles', 'delete')): ?>
<form method="POST" action="admin_roles.php" class="d-inline" onsubmit="return confirm('<?= h(t('Delete this role?', 'حذف هذا الدور؟')) ?>');">
<input type="hidden" name="action" value="delete">
<input type="hidden" name="id" value="<?= h($r['id']) ?>">
<button class="btn btn-outline-danger" type="submit">
<svg width="16" height="16" fill="currentColor" class="me-1" viewBox="0 0 16 16"><path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0V6z"/><path fill-rule="evenodd" d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1v1zM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4H4.118zM2.5 3V2h11v1h-11z"/></svg><?= h(t('Delete', 'حذف')) ?>
</button>
</form>
<?php endif; ?>
</div>
</td>
</tr>
<?php endforeach; ?>
<?php if (empty($roles)): ?>
<tr><td colspan="3" class="text-center py-4 text-secondary"><?= h(t('No roles found.', 'لا توجد أدوار.')) ?></td></tr>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
<!-- Role Modal -->
<div class="modal fade" id="roleModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<form class="modal-content" method="POST" action="admin_roles.php">
<input type="hidden" name="action" id="roleAction" value="add">
<input type="hidden" name="id" id="roleId" value="0">
<div class="modal-header">
<h5 class="modal-title" id="roleModalTitle"><?= h(t('Add Role Group', 'إضافة مجموعة صلاحيات')) ?></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="row mb-3">
<div class="col-md-6">
<label class="form-label"><?= h(t('Role Name', 'اسم الدور')) ?></label>
<input type="text" class="form-control" name="name" id="roleName" required>
</div>
<div class="col-md-6">
<label class="form-label"><?= h(t('Description', 'الوصف')) ?></label>
<input type="text" class="form-control" name="description" id="roleDesc">
</div>
</div>
<h6 class="mt-4 mb-3"><?= h(t('Permissions', 'الصلاحيات')) ?></h6>
<div class="table-responsive">
<table class="table table-bordered table-sm align-middle">
<thead class="bg-light text-center">
<tr>
<th class="text-start"><?= h(t('Page', 'الصفحة')) ?></th>
<th><?= h(t('View', 'عرض')) ?></th>
<th><?= h(t('Add', 'إضافة')) ?></th>
<th><?= h(t('Edit', 'تعديل')) ?></th>
<th><?= h(t('Delete', 'حذف')) ?></th>
</tr>
</thead>
<tbody id="permissionsTbody">
<?php foreach($pages as $p => $pname): ?>
<tr>
<td class="text-start fw-bold"><?= h($pname) ?></td>
<td class="text-center"><input class="form-check-input perm-chk perm-chk-view" type="checkbox" name="perms[<?= h($p) ?>][view]" value="1" data-page="<?= h($p) ?>"></td>
<td class="text-center"><input class="form-check-input perm-chk perm-chk-add" type="checkbox" name="perms[<?= h($p) ?>][add]" value="1" data-page="<?= h($p) ?>"></td>
<td class="text-center"><input class="form-check-input perm-chk perm-chk-edit" type="checkbox" name="perms[<?= h($p) ?>][edit]" value="1" data-page="<?= h($p) ?>"></td>
<td class="text-center"><input class="form-check-input perm-chk perm-chk-delete" type="checkbox" name="perms[<?= h($p) ?>][delete]" value="1" data-page="<?= h($p) ?>"></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal"><?= h(t('Cancel', 'إلغاء')) ?></button>
<button type="submit" class="btn btn-dark" id="btnSaveRole"><?= h(t('Save', 'حفظ')) ?></button>
</div>
</form>
</div>
</div>
<script>
function editRole(role) {
// reset checkboxes
document.querySelectorAll('.perm-chk').forEach(c => c.checked = false);
if (role) {
document.getElementById('roleAction').value = 'edit';
document.getElementById('roleId').value = role.id;
document.getElementById('roleModalTitle').innerText = '<?= h(t('Edit Role Group', 'تعديل مجموعة الصلاحيات')) ?>';
document.getElementById('roleName').value = role.name;
document.getElementById('roleDesc').value = role.description || '';
if (role.permissions) {
for (let p in role.permissions) {
let perms = role.permissions[p];
if (perms.can_view == 1) { let el = document.querySelector(`input[name="perms[${p}][view]"]`); if(el) el.checked = true; }
if (perms.can_add == 1) { let el = document.querySelector(`input[name="perms[${p}][add]"]`); if(el) el.checked = true; }
if (perms.can_edit == 1) { let el = document.querySelector(`input[name="perms[${p}][edit]"]`); if(el) el.checked = true; }
if (perms.can_delete == 1) { let el = document.querySelector(`input[name="perms[${p}][delete]"]`); if(el) el.checked = true; }
}
}
let isSystem = role.is_system == 1;
document.getElementById('roleName').readOnly = isSystem;
document.getElementById('roleDesc').readOnly = isSystem;
document.querySelectorAll('.perm-chk').forEach(c => c.disabled = isSystem);
document.getElementById('btnSaveRole').style.display = isSystem ? 'none' : 'block';
} else {
document.getElementById('roleAction').value = 'add';
document.getElementById('roleId').value = '0';
document.getElementById('roleModalTitle').innerText = '<?= h(t('Add Role Group', 'إضافة مجموعة صلاحيات')) ?>';
document.getElementById('roleName').value = '';
document.getElementById('roleDesc').value = '';
document.getElementById('roleName').readOnly = false;
document.getElementById('roleDesc').readOnly = false;
document.querySelectorAll('.perm-chk').forEach(c => c.disabled = false);
document.getElementById('btnSaveRole').style.display = 'block';
}
}
</script>