reconstruction of the project
This commit is contained in:
+144
-65
@@ -2,12 +2,18 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use App\Models\BaseModel;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class UserRole extends BaseModel
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
protected $table = 'user_roles';
|
||||
protected $primaryKey = 'id';
|
||||
|
||||
protected $fillable = [
|
||||
'user_id',
|
||||
'role_id',
|
||||
@@ -16,82 +22,155 @@ class UserRole extends BaseModel
|
||||
'deleted_at',
|
||||
'updated_by',
|
||||
];
|
||||
public $timestamps = true;
|
||||
const CREATED_AT = 'created_at';
|
||||
const UPDATED_AT = 'updated_at';
|
||||
protected $deletedField = 'deleted_at';
|
||||
|
||||
/**
|
||||
* ✅ Fetch all role names assigned to a specific user
|
||||
*
|
||||
* @param int $userId
|
||||
* @return array Array of roles, e.g., [['name' => 'parent'], ['name' => 'teacher']]
|
||||
protected $casts = [
|
||||
'user_id' => 'integer',
|
||||
'role_id' => 'integer',
|
||||
'updated_by' => 'integer',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'deleted_at' => 'datetime',
|
||||
];
|
||||
|
||||
/* ============================================================
|
||||
* Relationships
|
||||
* ============================================================
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$users = $this->db->table('users')
|
||||
->select('users.*')
|
||||
->join('user_roles', 'user_roles.user_id = users.id')
|
||||
->join('roles', 'roles.id = user_roles.role_id')
|
||||
->whereNotIn('roles.name', ['parent', 'teacher'])
|
||||
->groupBy('users.id') // prevent duplicates if user has multiple roles
|
||||
->get()
|
||||
->getResultArray();
|
||||
|
||||
return view('expenses/create', ['users' => $users]);
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class, 'user_id');
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 🔁 Deprecated: Use getAllRolesByUserId instead
|
||||
* Get the first role name by user ID
|
||||
*
|
||||
* @param int $userId
|
||||
* @return string|null
|
||||
*/
|
||||
public function getRolesByUserId(int $userId): array
|
||||
{
|
||||
$roles = $this->select('roles.name as role_name')
|
||||
->join('roles', 'roles.id = user_roles.role_id')
|
||||
->where('user_roles.user_id', $userId)
|
||||
->get()
|
||||
->getResultArray();
|
||||
|
||||
// Always return an array
|
||||
return is_array($roles) ? $roles : [];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* ✅ Insert or update a role assignment
|
||||
*
|
||||
* @param int $userId
|
||||
* @param int $roleId
|
||||
* @return bool|int
|
||||
*/
|
||||
public function updateOrInsertRole($userId, $roleId)
|
||||
public function role(): BelongsTo
|
||||
{
|
||||
// Check if this exact (user_id, role_id) already exists
|
||||
$exists = $this->where([
|
||||
'user_id' => $userId,
|
||||
'role_id' => $roleId
|
||||
])->first();
|
||||
return $this->belongsTo(Role::class, 'role_id');
|
||||
}
|
||||
|
||||
if ($exists) {
|
||||
// Already exists, nothing to do
|
||||
/* ============================================================
|
||||
* 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);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* CI-compatible methods (converted)
|
||||
* ============================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
* CI: 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();
|
||||
}
|
||||
|
||||
/**
|
||||
* CI: 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;
|
||||
}
|
||||
|
||||
// Otherwise, insert new user-role mapping
|
||||
return $this->insert([
|
||||
static::query()->create([
|
||||
'user_id' => $userId,
|
||||
'role_id' => $roleId,
|
||||
'updated_by' => session()->get('user_id')
|
||||
'updated_by' => $editorId,
|
||||
]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* Replacement for the CI "create()" method (query only)
|
||||
* ============================================================
|
||||
* In Laravel, view rendering belongs in Controllers, not Models.
|
||||
* This returns the user list that your CI method was building.
|
||||
*
|
||||
* CI 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'],
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user