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'); } } }