Files
alrahma_sunday_school_api/app/Models/UserRole.php
T
2026-06-09 01:25:14 -04:00

184 lines
5.6 KiB
PHP

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\DB;
class UserRole extends BaseModel
{
public $timestamps = true;
use SoftDeletes;
protected $table = 'user_roles';
protected $fillable = [
'user_id',
'role_id',
'semester',
'school_year',
'created_at',
'updated_at',
'updated_by',
'deleted_at',
];
protected $casts = [
'user_id' => 'integer',
'role_id' => 'integer',
'updated_by' => 'integer',
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
];
/* ============================================================
* Relationships
* ============================================================
*/
public function user(): BelongsTo
{
return $this->belongsTo(User::class, 'user_id');
}
public function role(): BelongsTo
{
return $this->belongsTo(Role::class, 'role_id');
}
/* ============================================================
* Scopes
* ============================================================
*/
public function scopeForUser(Builder $q, int $userId): Builder
{
return $q->where('user_id', $userId);
}
public function scopeForRole(Builder $q, int $roleId): Builder
{
return $q->where('role_id', $roleId);
}
public function scopeForSchoolYear(Builder $q, ?string $schoolYear): Builder
{
if ($schoolYear === null || trim($schoolYear) === '') {
return $q;
}
return $q->where('school_year', $schoolYear);
}
/* ============================================================
* legacy-compatible methods (converted)
* ============================================================
*/
/**
* legacy: getRolesByUserId($userId)
* Returns: [ ['role_name' => 'parent'], ['role_name' => 'teacher'] ]
*/
public static function getRolesByUserId(int $userId): array
{
return static::query()
->selectRaw('roles.name as role_name')
->join('roles', 'roles.id', '=', 'user_roles.role_id')
->where('user_roles.user_id', $userId)
->whereNull('user_roles.deleted_at')
->orderBy('roles.priority', 'asc')
->orderBy('roles.name', 'asc')
->get()
->map(fn ($r) => ['role_name' => (string) $r->role_name])
->all();
}
/**
* legacy: updateOrInsertRole($userId, $roleId)
* Idempotent (does nothing if already exists and not soft-deleted).
* If the row exists but is soft-deleted, restores it.
*/
public static function updateOrInsertRole(int $userId, int $roleId, ?int $editorId = null): bool
{
$editorId = $editorId ?? (auth()->id() ?? null);
$existing = static::withTrashed()
->where('user_id', $userId)
->where('role_id', $roleId)
->first();
if ($existing) {
if ($existing->trashed()) {
$existing->restore();
}
// keep updated_by fresh
if ($editorId !== null) {
$existing->updated_by = $editorId;
$existing->save();
}
return true;
}
static::query()->create([
'user_id' => $userId,
'role_id' => $roleId,
'updated_by' => $editorId,
]);
return true;
}
/* ============================================================
* Replacement for the legacy "create()" method (query only)
* ============================================================
* In Laravel, view rendering belongs in Controllers, not Models.
* This returns the user list that your legacy method was building.
*
* legacy logic:
* users joined to roles through user_roles, excluding parent/teacher,
* groupBy users.id to avoid duplicates.
*/
public static function usersExcludingRoles(array $excludedRoleNames = ['parent', 'teacher']): array
{
$excluded = array_values(array_unique(array_filter(array_map('strval', $excludedRoleNames))));
$excludedLower = array_map('strtolower', $excluded);
$placeholders = implode(',', array_fill(0, count($excludedLower), '?'));
return DB::table('users')
->select('users.*')
->join('user_roles', 'user_roles.user_id', '=', 'users.id')
->join('roles', 'roles.id', '=', 'user_roles.role_id')
->whereNull('user_roles.deleted_at')
->whereRaw("LOWER(roles.name) NOT IN ($placeholders)", $excludedLower)
->groupBy('users.id')
->orderBy('users.lastname', 'asc')
->orderBy('users.firstname', 'asc')
->get()
->map(fn ($r) => (array) $r)
->all();
}
/* ============================================================
* Optional validation helper
* ============================================================
*/
public static function rules(bool $updating = false): array
{
$req = $updating ? 'sometimes' : 'required';
return [
'user_id' => [$req, 'integer', 'min:1', 'exists:users,id'],
'role_id' => [$req, 'integer', 'min:1', 'exists:roles,id'],
'semester' => ['nullable', 'string', 'max:20'],
'school_year' => ['nullable', 'string', 'max:20'],
'updated_by' => ['nullable', 'integer'],
];
}
}