Files
alrahma_sunday_school_api/app/Services/Settings/SchoolCalendar/SchoolCalendarNotificationService.php
T
2026-06-09 00:03:03 -04:00

120 lines
3.9 KiB
PHP

<?php
namespace App\Services\Settings\SchoolCalendar;
use App\Models\User;
use App\Services\ApplicationUrlService;
use App\Services\EmailService;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class SchoolCalendarNotificationService
{
public function __construct(
private EmailService $emailService,
private ApplicationUrlService $urls,
) {}
public function notify(array $event, array $targets): array
{
if (empty($event) || empty(array_filter($targets))) {
return [];
}
$subject = $this->buildSubject($event);
$body = $this->buildBody($event);
$results = [];
foreach ($targets as $group => $enabled) {
if (! $enabled) {
continue;
}
$emails = $this->collectEmailsForGroup($group);
if (empty($emails)) {
Log::warning("SchoolCalendar: no recipient emails for {$group}.");
$results[$group] = null;
continue;
}
$to = $emails[0] ?? '';
$ok = $this->emailService->send($to, $subject, $body, 'general', [], $emails);
if (! $ok) {
Log::warning("SchoolCalendar: failed to send calendar notification to {$group}.");
}
$results[$group] = $ok;
}
return $results;
}
private function buildSubject(array $event): string
{
$title = trim((string) ($event['title'] ?? 'School Calendar Update'));
$typeSegment = ! empty($event['event_type']) ? ' ('.$event['event_type'].')' : '';
return 'School Calendar: '.$title.$typeSegment;
}
private function buildBody(array $event): string
{
$calendarUrl = $this->urls->spaAdministratorCalendarViewUrl();
$title = trim((string) ($event['title'] ?? 'School Calendar Update'));
$date = (string) ($event['date'] ?? '');
$description = trim((string) ($event['description'] ?? ''));
$body = '<h3>'.e($title).'</h3>';
$body .= '<p><strong>Date:</strong> '.e($date).'</p>';
if ($description !== '') {
$body .= '<p>'.nl2br(e($description)).'</p>';
}
$body .= '<p><a href="'.e($calendarUrl).'">View calendar</a></p>';
return $body;
}
private function collectEmailsForGroup(string $group): array
{
return match ($group) {
'parents' => $this->normalizeEmails(User::getParents()),
'teachers' => $this->normalizeEmails(User::getAllTeachers()),
'admins' => $this->normalizeEmails($this->fetchAdminRows()),
default => [],
};
}
private function normalizeEmails(array $rows): array
{
$emails = [];
foreach ($rows as $row) {
$email = trim((string) ($row['email'] ?? ''));
if ($email === '' || ! filter_var($email, FILTER_VALIDATE_EMAIL)) {
continue;
}
$emails[$email] = true;
}
return array_values(array_keys($emails));
}
private function fetchAdminRows(): array
{
$excluded = ['guest', 'teacher', 'teacher_assistant', 'parent'];
$escaped = array_map(static fn ($value) => "'".addslashes($value)."'", $excluded);
$excludedList = implode(', ', $escaped);
$builder = DB::table('users as u')
->selectRaw("u.id, u.firstname, u.lastname, u.email, MAX(CASE WHEN LOWER(COALESCE(r.slug, r.name)) NOT IN({$excludedList}) THEN 1 ELSE 0 END) AS is_admin")
->join('user_roles as ur', 'ur.user_id', '=', 'u.id')
->join('roles as r', 'r.id', '=', 'ur.role_id')
->where('r.is_active', 1)
->whereNotNull('u.email')
->where('u.email', '!=', '')
->groupBy('u.id', 'u.firstname', 'u.lastname', 'u.email')
->having('is_admin', 1);
return $builder->get()->map(fn ($r) => (array) $r)->all();
}
}