Files
alrahma_sunday_school_api/app/Services/Badges/BadgePdfService.php
T
2026-03-08 16:33:24 -04:00

196 lines
6.6 KiB
PHP

<?php
namespace App\Services\Badges;
use FPDF;
use Illuminate\Http\Response;
class BadgePdfService
{
public function __construct(
protected BadgeUserLookupService $lookupService,
protected BadgePrintLogService $printLogService,
protected BadgeTextFormatter $formatter
) {
}
public function generate(
array $userIds,
?string $schoolYear,
array $rolesMap = [],
array $classesMap = [],
?int $actorId = null
): Response {
$userIds = $this->formatter->normalizeIds($userIds);
$pdf = new FPDF('P', 'mm', 'A4');
$pdf->SetAutoPageBreak(false);
$badgeW = 95;
$badgeH = 67;
$marginL = 14;
$marginT = 6;
$gutterX = 0;
$gutterY = 0;
$cols = 2;
$rows = 4;
$perPage = $cols * $rows;
$pagesAdded = 0;
$i = 0;
$seen = [];
foreach ($userIds as $uid) {
$info = $this->lookupService->getUserInfoById($uid, $schoolYear);
if (!$info || !is_array($info)) {
continue;
}
$userId = (int) ($info['user_id'] ?? $uid);
$name = $this->formatter->norm($info['name'] ?? '');
$postedRole = $rolesMap[$userId] ?? null;
$roleResolved = $postedRole !== null
? $postedRole
: $this->formatter->resolveRole($info);
$roleResolved = $this->formatter->formatRole((string) $roleResolved);
$info['role_resolved'] = $roleResolved;
if (!empty($classesMap[$userId])) {
$info['class_section_name'] = (string) $classesMap[$userId];
}
$class = $this->formatter->norm($info['class_section_name'] ?? '');
$badgeKey = strtolower(trim($userId . '|' . $name . '|' . $roleResolved . '|' . $class));
if (isset($seen[$badgeKey])) {
continue;
}
$seen[$badgeKey] = true;
if (($i % $perPage) === 0) {
$pdf->AddPage();
$pagesAdded++;
}
$indexOnPage = $i % $perPage;
$row = intdiv($indexOnPage, $cols);
$col = $indexOnPage % $cols;
$x = $marginL + $col * ($badgeW + $gutterX);
$y = $marginT + $row * ($badgeH + $gutterY);
$this->drawBadgeInCell($pdf, $info, $x, $y, $badgeW, $badgeH, $schoolYear);
$i++;
}
if ($pagesAdded === 0) {
$pdf->AddPage();
$pdf->SetFont('Arial', '', 10);
$pdf->SetXY(10, 20);
$pdf->MultiCell(0, 6, 'No valid staff selected or data not found.', 0, 'L');
}
$pdfString = $pdf->Output('S');
$this->printLogService->logSafely(
userIds: $userIds,
actorId: $actorId,
schoolYear: $schoolYear,
rolesMap: $rolesMap,
classesMap: $classesMap,
copies: 1
);
return response($pdfString, 200, [
'Content-Type' => 'application/pdf',
'Content-Disposition' => 'inline; filename="Staff_Badges.pdf"',
]);
}
protected function drawBadgeInCell(FPDF $pdf, array $data, float $x, float $y, float $w, float $h, ?string $schoolYear): void
{
$pdf->SetFillColor(255, 255, 255);
$pdf->Rect($x, $y, $w, $h, 'F');
$pdf->SetDrawColor(200, 200, 200);
$pdf->Rect($x, $y, $w, $h);
$logoSize = 6;
if (!empty($data['school_logo']) && file_exists($data['school_logo'])) {
$pdf->Image($data['school_logo'], $x + $w - 6 - $logoSize, $y + 4, $logoSize + 3, $logoSize - 1);
}
if (!empty($data['isgl_logo']) && file_exists($data['isgl_logo'])) {
$pdf->Image($data['isgl_logo'], $x + 4, $y + 4, $logoSize + 3, $logoSize - 1);
}
$padX = 4;
$cursorY = $y + 4 + $logoSize + 2;
$schoolName = strtoupper($this->formatter->norm($data['school_name'] ?? 'AL RAHMA SUNDAY SCHOOL'));
$pdf->SetFont('Arial', '', 16);
$pdf->SetXY($x + $padX, $cursorY);
$pdf->MultiCell($w - 2 * $padX, 5, $this->formatter->toPdf($schoolName), 0, 'C');
$pdf->Ln(9);
$pdf->SetFont('Arial', 'B', 14);
$pdf->SetX($x + $padX);
$name = strtoupper($this->formatter->norm($data['name'] ?? 'STAFF'));
$pdf->Cell($w - 2 * $padX, 6, $this->formatter->toPdf($name), 0, 1, 'C');
$roleResolved = $this->formatter->norm((string) ($data['role_resolved'] ?? ''));
if ($roleResolved === '') {
$roleResolved = $this->formatter->resolveRole($data);
}
if ($roleResolved !== '') {
$roleResolved = $this->formatter->formatRole($roleResolved);
}
$classRaw = $this->formatter->norm($data['class_section_name'] ?? '');
$class = $this->formatter->formatClass($classRaw);
$detectSrc = strtolower($this->formatter->norm(
($data['roles_raw'] ?? '') !== '' ? $data['roles_raw'] : (($data['role_name_raw'] ?? '') !== '' ? $data['role_name_raw'] : $roleResolved)
));
$isTeacherish = str_contains($detectSrc, 'teacher') || preg_match('/\bta\b/', $detectSrc);
if ($isTeacherish && $class !== '') {
if (strtolower($class) === 'youth') {
$display = 'Youth ' . $roleResolved;
} elseif ($class === 'KG') {
$display = 'KG ' . $roleResolved;
} else {
$display = 'Grade ' . $class . ' ' . $roleResolved;
}
} elseif ($roleResolved !== '') {
$display = $roleResolved;
} elseif ($class !== '') {
$display = $class;
} else {
$display = 'STAFF';
}
$pdf->Ln(6);
$pdf->SetFont('Arial', '', 14);
$displayOut = $this->formatter->toPdf($display);
$maxTextWidth = $w - 2 * $padX;
$best = $this->formatter->fitText($pdf, $displayOut, 11, 7, $maxTextWidth);
$pdf->SetFont('Arial', '', $best + 4);
if ($pdf->GetStringWidth($displayOut) <= $maxTextWidth) {
$pdf->SetX($x + $padX);
$pdf->Cell($maxTextWidth, 5, $displayOut, 0, 1, 'C');
} else {
$pdf->SetX($x + $padX);
$pdf->MultiCell($maxTextWidth, 5, $displayOut, 0, 'C');
}
$footerYear = $this->formatter->norm((string) ($schoolYear ?? ($data['school_year'] ?? '')));
if ($footerYear !== '') {
$pdf->SetFont('Arial', 'I', 14);
$pdf->SetXY($x + $padX, $y + $h - 9);
$pdf->Cell($w - 2 * $padX, 4, $this->formatter->toPdf($footerYear), 0, 0, 'C');
}
}
}