196 lines
6.6 KiB
PHP
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');
|
|
}
|
|
}
|
|
} |