Files
alrahma_sunday_school_api/app/Services/Attendance/AttendancePolicyService.php
T

129 lines
4.0 KiB
PHP

<?php
namespace App\Services\Attendance;
use App\Models\Role;
use Illuminate\Contracts\Auth\Authenticatable;
class AttendancePolicyService
{
public function canEditDay(array $dayRow, array $currentUser): bool
{
$status = strtolower((string)($dayRow['status'] ?? 'draft'));
$roles = array_map([$this, 'normalizeRole'], (array)($currentUser['roles'] ?? []));
$permissions = array_map('strtolower', (array)($currentUser['permissions'] ?? []));
$isAdmin = $this->isAdminLike($roles, $permissions);
$isTeacher = in_array('teacher', $roles, true) || in_array('ta', $roles, true) || in_array('teacher_assistant', $roles, true);
if ($status === 'finalized' || $status === 'published') {
return $isAdmin;
}
if ($status === 'submitted') {
return $isAdmin;
}
if ($status === 'draft') {
return $isAdmin || $isTeacher;
}
return $isAdmin;
}
public function isTeacher(array $roles): bool
{
$roles = array_map([$this, 'normalizeRole'], $roles);
return in_array('teacher', $roles, true)
|| in_array('ta', $roles, true)
|| in_array('teacher_assistant', $roles, true)
|| in_array('assistant_teacher', $roles, true);
}
public function isAdminLike(array $roles, array $permissions = []): bool
{
$roles = array_map([$this, 'normalizeRole'], $roles);
$adminTokens = $this->adminRoleTokens();
if (!empty($adminTokens) && count(array_intersect($roles, $adminTokens)) > 0) {
return true;
}
foreach ($permissions as $permission) {
$permission = strtolower(trim((string) $permission));
if (str_contains($permission, 'attendance.manage') || str_contains($permission, 'attendance.admin')) {
return true;
}
}
return false;
}
public function normalizeRole(?string $role): string
{
return str_replace([' ', '-'], '_', strtolower(trim((string)$role)));
}
public function canManageEarlyDismissals(array $userRoles): bool
{
$normalized = array_map([$this, 'normalizeRole'], $userRoles);
$adminTokens = $this->adminRoleTokens();
$isAdminLike = count(array_intersect($normalized, $adminTokens)) > 0;
$isTeacher = in_array('teacher', $normalized, true) || in_array('teacher_assistant', $normalized, true);
return $isAdminLike || $isTeacher;
}
private function adminRoleTokens(): array
{
static $cache = null;
if (is_array($cache)) {
return $cache;
}
$tokens = [];
$normalize = fn (string $value): string => $this->normalizeRole($value);
try {
$rows = Role::query()
->where('is_active', 1)
->get(['name', 'slug']);
$excluded = array_map($normalize, [
'guest',
'parent',
'student',
'teacher',
'teacher_assistant',
'ta',
]);
foreach ($rows as $row) {
$name = $normalize((string) ($row->name ?? ''));
$slug = $normalize((string) ($row->slug ?? $name));
if ($name === '' && $slug === '') {
continue;
}
if (in_array($slug, $excluded, true) || in_array($name, $excluded, true)) {
continue;
}
if ($name !== '') {
$tokens[$name] = true;
}
if ($slug !== '') {
$tokens[$slug] = true;
}
}
} catch (\Throwable) {
// ignore and fall back to defaults
}
foreach (['administrator', 'admin', 'principal', 'vice_principal', 'vice-principal'] as $fallback) {
$tokens[$normalize($fallback)] = true;
}
$cache = array_keys($tokens);
return $cache;
}
}