187 lines
7.2 KiB
PHP
187 lines
7.2 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Parents;
|
|
|
|
use App\Controllers\View\EmailController;
|
|
use App\Models\AuthorizedUserModel;
|
|
use App\Models\UserModel;
|
|
use App\Services\SchoolIdService;
|
|
use CodeIgniter\Database\BaseConnection;
|
|
use Exception;
|
|
|
|
class ParentAccountService
|
|
{
|
|
public function __construct(
|
|
private readonly BaseConnection $db,
|
|
private readonly UserModel $userModel,
|
|
private readonly AuthorizedUserModel $authorizedUsersModel,
|
|
) {
|
|
}
|
|
|
|
public function canAccessUserRecord(int $requestedUserId, int $sessionUserId, array $sessionRoles): bool
|
|
{
|
|
if ($sessionUserId <= 0 || $requestedUserId <= 0) {
|
|
return false;
|
|
}
|
|
|
|
if ($sessionUserId === $requestedUserId) {
|
|
return true;
|
|
}
|
|
|
|
$roles = array_map(
|
|
static fn ($role): string => strtolower(trim((string) $role)),
|
|
array_filter($sessionRoles)
|
|
);
|
|
|
|
return (bool) array_intersect($roles, ['administrator', 'administrative staff', 'principal', 'admin']);
|
|
}
|
|
|
|
public function isEmailUnique(string $email): bool
|
|
{
|
|
foreach (['users' => 'email', 'emergency_contacts' => 'email'] as $table => $column) {
|
|
if ($this->db->table($table)->where($column, $email)->countAllResults() > 0) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public function createRelatedUser(array $userData, string $relationToStudent, string $semester, string $schoolYear): int|false
|
|
{
|
|
$schoolIdService = new SchoolIdService();
|
|
$token = bin2hex(random_bytes(48));
|
|
$tokenHash = hash('sha256', $token);
|
|
$userType = in_array(strtolower($relationToStudent), ['wife', 'husband'], true) ? 'Secondary' : 'Tertiary';
|
|
|
|
$validation = \Config\Services::validation();
|
|
$validation->setRules([
|
|
'firstname' => [
|
|
'label' => 'First Name',
|
|
'rules' => 'required|min_length[2]|max_length[100]|regex_match[/^[A-Za-z\s\-]+$/]',
|
|
'errors' => ['regex_match' => 'First name may only contain letters, spaces, and dashes.'],
|
|
],
|
|
'lastname' => [
|
|
'label' => 'Last Name',
|
|
'rules' => 'required|min_length[2]|max_length[100]|regex_match[/^[A-Za-z\s\-]+$/]',
|
|
'errors' => ['regex_match' => 'Last name may only contain letters, spaces, and dashes.'],
|
|
],
|
|
'email' => [
|
|
'label' => 'Email Address',
|
|
'rules' => 'required|valid_email|max_length[150]|is_unique[users.email]',
|
|
'errors' => ['is_unique' => 'This email is already registered.'],
|
|
],
|
|
'cellphone' => [
|
|
'label' => 'Cell Phone',
|
|
'rules' => 'required|regex_match[/^\d{10}$/]',
|
|
'errors' => ['regex_match' => 'Phone number must be exactly 10 digits.'],
|
|
],
|
|
'gender' => 'required|in_list[Male,Female]',
|
|
'city' => 'required|max_length[100]',
|
|
'state' => 'required|max_length[100]',
|
|
'zip' => 'required|regex_match[/^\d{5}$/]',
|
|
]);
|
|
|
|
if (! $validation->run($userData)) {
|
|
log_message('error', 'User creation failed due to invalid data: ' . json_encode($validation->getErrors()));
|
|
return false;
|
|
}
|
|
|
|
$userEntry = [
|
|
'firstname' => ucfirst(strtolower($userData['firstname'])),
|
|
'lastname' => ucfirst(strtolower($userData['lastname'])),
|
|
'gender' => $userData['gender'],
|
|
'cellphone' => $userData['cellphone'],
|
|
'email' => strtolower($userData['email']),
|
|
'address_street' => $userData['address_street'] ?? '',
|
|
'apt' => $userData['apt'] ?? null,
|
|
'city' => ucfirst(strtolower($userData['city'])),
|
|
'state' => strtoupper($userData['state']),
|
|
'zip' => $userData['zip'],
|
|
'accept_school_policy' => $userData['accept_school_policy'] ?? 0,
|
|
'token' => $tokenHash,
|
|
'is_verified' => 0,
|
|
'status' => 'Inactive',
|
|
'user_type' => $userType,
|
|
'semester' => $semester,
|
|
'school_year' => $schoolYear,
|
|
'school_id' => $schoolIdService->generateUserSchoolId(),
|
|
];
|
|
|
|
try {
|
|
if (! $this->userModel->insert($userEntry)) {
|
|
log_message('error', 'Failed to insert user: ' . print_r($this->userModel->errors(), true));
|
|
return false;
|
|
}
|
|
|
|
$userId = (int) $this->userModel->getInsertID();
|
|
$this->sendActivationEmail((string) $userData['email'], $token);
|
|
log_message('info', "User with ID $userId created successfully and activation email sent.");
|
|
|
|
return $userId;
|
|
} catch (Exception $e) {
|
|
log_message('error', 'Exception during user creation: ' . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public function updateAuthorizedUsers(int $userId, array $data): void
|
|
{
|
|
$validation = \Config\Services::validation();
|
|
$validation->setRules([
|
|
'email' => [
|
|
'label' => 'Email',
|
|
'rules' => 'required|valid_email|max_length[150]',
|
|
'errors' => [
|
|
'required' => 'Email is required.',
|
|
'valid_email' => 'Please provide a valid email address.',
|
|
'max_length' => 'Email must be less than 150 characters.',
|
|
],
|
|
],
|
|
'name' => [
|
|
'label' => 'Name',
|
|
'rules' => 'required|min_length[3]|max_length[100]|regex_match[/^[A-Za-z\s\-]+$/]',
|
|
'errors' => [
|
|
'required' => 'Name is required.',
|
|
'regex_match' => 'Name can only contain letters, spaces, and dashes.',
|
|
'min_length' => 'Name must be at least 3 characters long.',
|
|
'max_length' => 'Name must be less than 100 characters.',
|
|
],
|
|
],
|
|
]);
|
|
|
|
if (! $validation->run($data)) {
|
|
log_message('error', 'Invalid authorized user data: ' . json_encode($validation->getErrors()));
|
|
return;
|
|
}
|
|
|
|
$existingAuthorizedUser = $this->authorizedUsersModel
|
|
->where('user_id', $userId)
|
|
->where('email', $data['email'])
|
|
->first();
|
|
|
|
if ($existingAuthorizedUser) {
|
|
$this->authorizedUsersModel->update($existingAuthorizedUser['id'], $data);
|
|
return;
|
|
}
|
|
|
|
$data['user_id'] = $userId;
|
|
$data['status'] = 'Pending';
|
|
$this->authorizedUsersModel->insert($data);
|
|
}
|
|
|
|
private function sendActivationEmail(string $email, string $token): void
|
|
{
|
|
$emailController = new EmailController();
|
|
$subject = 'Activate Your Account';
|
|
$activationLink = site_url('/user/confirm/' . $token);
|
|
$message = "Please click the following link to confirm your email and set your password: $activationLink";
|
|
|
|
if ($emailController->sendEmail($email, $subject, $message)) {
|
|
log_message('info', 'Activation email sent successfully to ' . $email);
|
|
} else {
|
|
log_message('error', 'Failed to send activation email to ' . $email);
|
|
}
|
|
}
|
|
}
|