130 lines
4.0 KiB
PHP
130 lines
4.0 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Attendance;
|
|
|
|
use App\Models\Role;
|
|
|
|
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;
|
|
}
|
|
}
|