37338-vm/_print_group_members_pdf.php
2026-03-02 20:46:20 +00:00

241 lines
7.6 KiB
PHP

<?php
// Start output buffering to prevent any accidental output before headers
ob_start();
require_once __DIR__ . '/db/config.php';
require_once __DIR__ . '/lib/ErrorHandler.php';
require_once __DIR__ . '/lib/tfpdf/tfpdf.php';
require_once __DIR__ . '/lib/tfpdf/font/unifont/ttfonts.php';
// Disable error display to avoid corrupting PDF output
ini_set('display_errors', 0);
error_reporting(E_ALL);
$group_name = $_GET['group_name'] ?? '';
if (empty($group_name)) {
while (ob_get_level() > 0) ob_end_clean();
http_response_code(400);
header('Content-Type: application/json');
echo json_encode(['success' => false, 'error' => 'Parameter group_name is required']);
exit;
}
try {
$db = db();
// 1. Fetch group by name
$stmt = $db->prepare('SELECT id, name FROM bni_groups WHERE LOWER(name) = LOWER(?)');
$stmt->execute([trim($group_name)]);
$group = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$group) {
while (ob_get_level() > 0) ob_end_clean();
http_response_code(404);
header('Content-Type: application/json');
echo json_encode(['success' => false, 'error' => 'Group not found']);
exit;
}
$groupId = $group['id'];
$groupRealName = $group['name'];
// 2. Fetch members
$stmt = $db->prepare('
SELECT
p.first_name,
p.last_name,
p.person_photo_path,
p.company_name,
p.company_logo_path,
p.business_description,
p.industry,
p.company_size
FROM people p
WHERE p.bni_group_id = ?
ORDER BY p.last_name ASC, p.first_name ASC
');
$stmt->execute([$groupId]);
$members = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (empty($members)) {
while (ob_get_level() > 0) ob_end_clean();
http_response_code(404);
header('Content-Type: application/json');
echo json_encode(['success' => false, 'error' => 'No members found in this group']);
exit;
}
// Helper to validate images before adding to PDF
$tempFiles = [];
function getVerifiedImagePath($path, &$tempFiles) {
if (empty($path)) return null;
// Local file
if (strpos($path, 'http') !== 0) {
$localPath = rtrim(realpath(__DIR__), '/') . '/' . ltrim($path, '/');
if (!file_exists($localPath)) return null;
$info = @getimagesize($localPath);
if ($info && in_array($info[2], [IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG])) {
return $localPath;
}
return null;
}
// URL
$ch = curl_init($path);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 3);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$data = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($code >= 200 && $code < 300 && $data) {
$tmp = tempnam(sys_get_temp_dir(), 'pdfimg_');
file_put_contents($tmp, $data);
$info = @getimagesize($tmp);
if ($info && in_array($info[2], [IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG])) {
$tempFiles[] = $tmp;
return $tmp;
}
@unlink($tmp);
}
return null;
}
// 3. Create PDF
$pdf = new tFPDF();
$pdf->AddFont('DejaVu', '', 'DejaVuSans.ttf', true);
$pdf->AddFont('DejaVu', 'B', 'DejaVuSans-Bold.ttf', true);
$pdf->SetMargins(15, 20, 15);
$pdf->SetAutoPageBreak(true, 15);
foreach ($members as $member) {
$pdf->AddPage();
// --- HEADER ---
$pdf->SetFont('DejaVu', 'B', 12);
$pdf->SetTextColor(150, 150, 150);
$pdf->Cell(0, 10, 'Grupa: ' . $groupRealName, 0, 1, 'R');
$pdf->Ln(5);
$pdf->SetTextColor(0, 0, 0);
// --- IMAGES ---
$yStart = $pdf->GetY();
$minY = $yStart;
// Left - Photo
if (!empty($member['person_photo_path'])) {
$validPath = getVerifiedImagePath($member['person_photo_path'], $tempFiles);
if ($validPath) {
@$pdf->Image($validPath, 15, $yStart, 40);
$minY = max($minY, $yStart + 50);
}
}
// Right - Logo
if (!empty($member['company_logo_path'])) {
$validPath = getVerifiedImagePath($member['company_logo_path'], $tempFiles);
if ($validPath) {
@$pdf->Image($validPath, 155, $yStart, 40);
$minY = max($minY, $yStart + 50);
}
}
// --- MAIN INFO ---
$pdf->SetY($yStart + 10);
$name = trim($member['first_name'] . ' ' . $member['last_name']);
if ($name === '') {
$name = 'Nieznany członek';
}
$pdf->SetFont('DejaVu', 'B', 22);
// Add margins for text so it doesn't overlap images
$pdf->SetLeftMargin(55);
$pdf->SetRightMargin(55);
$pdf->Cell(100, 12, $name, 0, 1, 'C');
$companyName = trim($member['company_name'] ?? '');
if ($companyName !== '') {
$pdf->SetFont('DejaVu', 'B', 16);
$pdf->SetTextColor(80, 80, 80);
$pdf->MultiCell(100, 8, $companyName, 0, 'C');
$pdf->SetTextColor(0, 0, 0);
}
// Reset margins
$pdf->SetLeftMargin(15);
$pdf->SetRightMargin(15);
$pdf->SetX(15);
// Ensure we draw details below the images
if ($pdf->GetY() < $minY) {
$pdf->SetY($minY + 5);
} else {
$pdf->Ln(10);
}
// --- DETAILS ---
$pdf->SetFont('DejaVu', 'B', 12);
// Industry
$pdf->Cell(45, 8, 'Branża:', 0, 0);
$pdf->SetFont('DejaVu', '', 12);
$industry = trim($member['industry'] ?? '');
$pdf->Cell(0, 8, $industry !== '' ? $industry : '-', 0, 1);
// Company Size
$pdf->SetFont('DejaVu', 'B', 12);
$pdf->Cell(45, 8, 'Wielkość firmy:', 0, 0);
$pdf->SetFont('DejaVu', '', 12);
$companySize = trim($member['company_size'] ?? '');
$pdf->Cell(0, 8, $companySize !== '' ? $companySize : '-', 0, 1);
$pdf->Ln(8);
// Description
$pdf->SetFont('DejaVu', 'B', 12);
$pdf->Cell(0, 8, 'Opis:', 0, 1);
$pdf->SetFont('DejaVu', '', 11);
$desc = trim($member['business_description'] ?? '');
if ($desc === '') {
$desc = 'Brak opisu.';
}
$pdf->MultiCell(0, 6, $desc);
}
// Clear buffer before sending headers
while (ob_get_level() > 0) ob_end_clean();
$safeName = preg_replace('/[^a-zA-Z0-9_\-]/', '_', strtolower($groupRealName));
$filename = 'lista_czlonkow_' . $safeName . '.pdf';
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="' . $filename . '"');
header('Cache-Control: private, max-age=0, must-revalidate');
header('Pragma: public');
// Output directly
$pdf->Output('D', $filename);
// Cleanup
foreach ($tempFiles as $tmp) {
@unlink($tmp);
}
exit;
} catch (Exception $e) {
while (ob_get_level() > 0) ob_end_clean();
http_response_code(500);
header('Content-Type: application/json');
echo json_encode(['success' => false, 'error' => 'Wystąpił błąd podczas generowania PDF', 'details' => $e->getMessage()]);
exit;
}