Generowanie pdf, z błędem

This commit is contained in:
Flatlogic Bot 2026-01-11 16:49:25 +00:00
parent eb3e723258
commit 274148ff8b
8 changed files with 2101 additions and 11 deletions

View File

@ -11,7 +11,7 @@ class WorkflowEngine {
$this->pdo = db();
}
public function getDashboardMatrix(?string $searchTerm = null, ?int $groupId = null, ?int $activeProcessDefinitionId = null): array {
public function getDashboardMatrix(?string $searchTerm = null, ?int $groupId = null, ?int $activeProcessDefinitionId = null, ?int $meetingFilterGroupId = null, ?string $meetingFilterDatetime = null): array {
// 1. Base query for people
$sql_people = "SELECT p.*, bg.name as bni_group_name FROM people p LEFT JOIN bni_groups bg ON p.bni_group_id = bg.id";
$params = [];
@ -37,6 +37,14 @@ class WorkflowEngine {
$params[':active_process_id'] = $activeProcessDefinitionId;
}
if ($meetingFilterGroupId && $meetingFilterDatetime) {
$meetingId = $this->getOrCreateMeeting($meetingFilterGroupId, $meetingFilterDatetime);
$sql_people .= " INNER JOIN meeting_attendance ma ON p.id = ma.person_id";
$where_clauses[] = "ma.meeting_id = :meeting_id";
$where_clauses[] = "ma.attendance_status IN ('present', 'absent', 'substitute')";
$params[':meeting_id'] = $meetingId;
}
if (!empty($where_clauses)) {
$sql_people .= " WHERE " . implode(" AND ", $where_clauses);
}
@ -834,4 +842,22 @@ class WorkflowEngine {
'guest_survey' => null,
];
}
public function getPeopleDetails(array $personIds): array {
if (empty($personIds)) {
return [];
}
$placeholders = implode(',', array_fill(0, count($personIds), '?'));
$sql = "SELECT p.id, p.first_name, p.last_name, p.company_name, p.industry, bg.name as bni_group_name
FROM people p
LEFT JOIN bni_groups bg ON p.bni_group_id = bg.id
WHERE p.id IN ($placeholders)";
$stmt = $this->pdo->prepare($sql);
$stmt->execute($personIds);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
}

117
_bulk_print_badges.php Normal file
View File

@ -0,0 +1,117 @@
<?php
// 1. Disable error reporting and start output buffering
error_reporting(0);
ini_set('display_errors', 0);
ob_start();
$correlation_id = uniqid('corr_');
error_log($correlation_id . ': Bulk print badges request started.');
require_once 'WorkflowEngine.php';
require_once 'lib/fpdf/fpdf.php';
session_start();
// Authentication check
if (!isset($_SESSION['user_id'])) {
if (ob_get_length()) ob_end_clean();
http_response_code(403);
header('Content-Type: application/json');
$error_message = 'Brak uprawnień.';
error_log($correlation_id . ': ' . $error_message);
echo json_encode(['error' => ['message' => $error_message], 'correlation_id' => $correlation_id]);
exit;
}
// Input validation
$person_ids_json = $_POST['person_ids'] ?? '[]';
$person_ids = json_decode($person_ids_json, true);
error_log($correlation_id . ': Received ' . count($person_ids) . ' person_ids.');
if (empty($person_ids)) {
if (ob_get_length()) ob_end_clean();
http_response_code(400);
header('Content-Type: application/json');
$error_message = 'Nie wybrano żadnych osób.';
error_log($correlation_id . ': ' . $error_message);
echo json_encode(['error' => ['message' => $error_message], 'correlation_id' => $correlation_id]);
exit;
}
$workflowEngine = new WorkflowEngine();
$peopleDetails = $workflowEngine->getPeopleDetails($person_ids);
error_log($correlation_id . ': Fetched ' . count($peopleDetails) . ' rows from database.');
class PDF extends FPDF
{
function __construct($orientation='P', $unit='mm', $size='A4')
{
parent::__construct($orientation, $unit, $size);
$this->AddFont('DejaVu','','DejaVuSans.php');
$this->AddFont('DejaVu','B','DejaVuSans-Bold.php');
}
function generateBadge($person) {
$this->AddPage();
$this->SetFont('DejaVu', 'B', 24);
$this->Cell(0, 20, $person['first_name'] . ' ' . $person['last_name'], 0, 1, 'C');
$this->Ln(10);
$this->SetFont('DejaVu', '', 16);
$details = [
'Firma:' => $person['company_name'],
'Branża:' => $person['industry'],
'Grupa BNI:' => $person['bni_group_name']
];
foreach ($details as $label => $value) {
$this->SetFont('DejaVu', 'B', 14);
$this->Cell(40, 10, $label, 0, 0);
$this->SetFont('DejaVu', '', 14);
$this->Cell(0, 10, $value ?? 'N/A', 0, 1);
$this->Ln(5);
}
}
}
$pdf = new PDF();
foreach ($peopleDetails as $person) {
// No need for converting the entire array, FPDF with iconv handles it.
$pdf->generateBadge($person);
}
// 2. Generate PDF content as a string
$pdfData = $pdf->Output('S');
error_log($correlation_id . ': PDF data generated. Length: ' . strlen($pdfData) . ' bytes.');
error_log($correlation_id . ': Memory usage: ' . memory_get_usage());
// 3. Validate PDF data
if (empty($pdfData) || !is_string($pdfData)) {
if (ob_get_length()) ob_end_clean();
http_response_code(500);
header('Content-Type: application/json');
$error_message = 'Failed to generate PDF data.';
error_log($correlation_id . ': ' . $error_message);
echo json_encode(['error' => ['message' => $error_message], 'correlation_id' => $correlation_id]);
exit;
}
// 4. Clean any potential output that occurred before this point
if (ob_get_length()) {
ob_end_clean();
}
// 5. Send correct headers
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="badges.pdf"');
header('Content-Transfer-Encoding: binary');
header('Cache-Control: private, max-age=0, must-revalidate');
header('Pragma: public');
header('Content-Length: ' . strlen($pdfData));
// 6. Output the raw PDF data and terminate
echo $pdfData;
exit;

103
index.php
View File

@ -27,8 +27,30 @@ if (isset($_GET['active_process_id']) && $_GET['active_process_id'] == @$_SESSIO
}
$_SESSION['last_active_process_id'] = $activeProcessId;
$meetingFilterGroupId = isset($_GET['meeting_filter_group_id']) && $_GET['meeting_filter_group_id'] !== '' ? (int)$_GET['meeting_filter_group_id'] : null;
$meetingFilterDatetime = $_GET['meeting_filter_datetime'] ?? null;
$matrixData = $workflowEngine->getDashboardMatrix($searchTerm, $groupId, $activeProcessId);
// Handle toggling of the active meeting filter
if ($meetingFilterGroupId && $meetingFilterDatetime &&
$meetingFilterGroupId == ($_SESSION['last_meeting_filter_group_id'] ?? null) &&
$meetingFilterDatetime == ($_SESSION['last_meeting_filter_datetime'] ?? null)) {
unset($_GET['meeting_filter_group_id']);
unset($_GET['meeting_filter_datetime']);
$redirectUrl = "index.php";
// Re-build the query string without the meeting filter parameters
$queryParams = $_GET;
if (!empty($queryParams)) {
$redirectUrl .= "?" . http_build_query($queryParams);
}
header("Location: " . $redirectUrl);
exit;
}
$_SESSION['last_meeting_filter_group_id'] = $meetingFilterGroupId;
$_SESSION['last_meeting_filter_datetime'] = $meetingFilterDatetime;
$matrixData = $workflowEngine->getDashboardMatrix($searchTerm, $groupId, $activeProcessId, $meetingFilterGroupId, $meetingFilterDatetime);
$people = $matrixData['people'];
$processes = $matrixData['definitions'];
$instances = $matrixData['instances'];
@ -84,6 +106,8 @@ $status_colors = [
<li><a class="dropdown-item" href="#" data-bs-toggle="modal" data-bs-target="#bulkStatusModal">Bulk Status Update</a></li>
<li><a class="dropdown-item" href="#" data-bs-toggle="modal" data-bs-target="#bulkEventModal">Bulk Add Event</a></li>
<li><a class="dropdown-item" href="#" data-bs-toggle="modal" data-bs-target="#bulkInitModal">Bulk Initialize Instances</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#" id="bulkPrintBadge">Drukuj badge</a></li>
</ul>
</div>
<button type="button" class="btn btn-success" data-bs-toggle="modal" data-bs-target="#createPersonModal">
@ -126,16 +150,20 @@ $status_colors = [
<?php endif; ?>
</tr>
<tr class="text-center">
<?php foreach ($spotkania_cols as $col): ?>
<th data-group-id="<?= $col['group_id'] ?>" data-meetings='<?= json_encode($col['meetings'] ?? []) ?>'>
<div class="d-flex justify-content-center align-items-center">
<button class="btn btn-sm btn-outline-secondary meeting-nav-btn meeting-prev-btn"><i class="bi bi-chevron-left"></i></button>
<div class="mx-2 text-center">
<?= htmlspecialchars($col['group_name']) ?><br>
<small class="meeting-date"></small>
<?php foreach ($spotkania_cols as $col):
$isMeetingFilterActive = ($meetingFilterGroupId == $col['group_id'] && $meetingFilterDatetime == ($col['meetings'][0] ?? null));
?>
<th data-group-id="<?= $col['group_id'] ?>" data-meetings='<?= json_encode($col['meetings'] ?? []) ?>' class="<?= $isMeetingFilterActive ? 'active-filter' : '' ?>">
<a href="#" class="text-decoration-none text-dark meeting-filter-link">
<div class="d-flex justify-content-center align-items-center">
<button class="btn btn-sm btn-outline-secondary meeting-nav-btn meeting-prev-btn"><i class="bi bi-chevron-left"></i></button>
<div class="mx-2 text-center">
<?= htmlspecialchars($col['group_name']) ?><br>
<small class="meeting-date"></small>
</div>
<button class="btn btn-sm btn-outline-secondary meeting-nav-btn meeting-next-btn"><i class="bi bi-chevron-right"></i></button>
</div>
<button class="btn btn-sm btn-outline-secondary meeting-nav-btn meeting-next-btn"><i class="bi bi-chevron-right"></i></button>
</div>
</a>
</th>
<?php endforeach; ?>
<?php foreach ($processes as $col): ?>
@ -734,6 +762,33 @@ document.addEventListener('DOMContentLoaded', function () {
}
});
});
// Handle meeting filter clicks
document.querySelectorAll('.meeting-filter-link').forEach(link => {
link.addEventListener('click', function(e) {
e.preventDefault();
const header = this.closest('th');
const isActive = header.classList.contains('active-filter');
const urlParams = new URLSearchParams(window.location.search);
if (isActive) {
urlParams.delete('meeting_filter_group_id');
urlParams.delete('meeting_filter_datetime');
} else {
const groupId = header.dataset.groupId;
// The meeting datetime is dynamic, so we need to get it from the elements
const firstDotInColumn = document.querySelector(`.meeting-dot[data-bni-group-id='${groupId}']`);
const meetingDatetime = firstDotInColumn ? firstDotInColumn.dataset.meetingDatetime : '';
if (groupId && meetingDatetime) {
urlParams.set('meeting_filter_group_id', groupId);
urlParams.set('meeting_filter_datetime', meetingDatetime);
}
}
window.location.href = 'index.php?' + urlParams.toString();
});
});
});
</script>
@ -804,6 +859,34 @@ document.addEventListener('DOMContentLoaded', function () {
setupBulkModal('bulkEventModal', 'bulkEventPersonIds');
setupBulkModal('bulkInitModal', 'bulkInitPersonIds');
const printBadgeBtn = document.getElementById('bulkPrintBadge');
if(printBadgeBtn) {
printBadgeBtn.addEventListener('click', function(e) {
e.preventDefault();
const selectedIds = Array.from(checkboxes).filter(c => c.checked).map(c => c.value);
if (selectedIds.length === 0) {
alert('Proszę zaznaczyć przynajmniej jedną osobę.');
return;
}
// Create a form to POST the data
const form = document.createElement('form');
form.method = 'post';
form.action = '_bulk_print_badges.php';
form.target = '_blank'; // Open in a new tab
const hiddenInput = document.createElement('input');
hiddenInput.type = 'hidden';
hiddenInput.name = 'person_ids';
hiddenInput.value = JSON.stringify(selectedIds);
form.appendChild(hiddenInput);
document.body.appendChild(form);
form.submit();
document.body.removeChild(form);
});
}
// Populate edit person modal
const editPersonModal = document.getElementById('editPersonModal');
if(editPersonModal) {

View File

@ -0,0 +1,20 @@
<?php
$type = 'TrueType';
$name = 'DejaVuSans-Bold';
$desc = array(
'Ascent' => 928,
'Descent' => -236,
'CapHeight' => 928,
'Flags' => 262148,
'FontBBox' => '[-917 -415 1682 1167]',
'ItalicAngle' => 0,
'StemV' => 165,
'MissingWidth' => 602,
);
$up = -100;
$ut = 50;
$cw = json_decode(file_get_contents(__DIR__ . '/dejavusansb_cw.json'), true);
$enc = 'cp1252';
$diff = '';
$file = 'dejavusansb.ttf.z';
$originalsize = 294260;

View File

@ -0,0 +1,20 @@
<?php
$type = 'TrueType';
$name = 'DejaVuSans';
$desc = array(
'Ascent' => 928,
'Descent' => -236,
'CapHeight' => 928,
'Flags' => 4,
'FontBBox' => '[-917 -415 1682 1167]',
'ItalicAngle' => 0,
'StemV' => 87,
'MissingWidth' => 540,
);
$up = -100;
$ut = 50;
$cw = json_decode(file_get_contents(__DIR__ . '/dejavusans_cw.json'), true);
$enc = 'cp1252';
$diff = '' ;
$file = 'dejavusans.ttf.z';
$originalsize = 294260;

View File

@ -0,0 +1 @@
{" ":278,"!":278,"\"":355,"#":556,"$":556,"%":889,"&":667,"' ":222,"":333,"":333,"*":389,"+":584,",":278,".":278,"-":333,"/":278,"":556,"":556,"":556,"":556,"":556,"":556,"":556,"":556,"":556,"":556,":":278,";":278,"<":584,"=":584,">":584,"?":556,"@":1015,"A":667,"B":667,"C":722,"D":722,"E":667,"F":611,"G":778,"H":722,"I":278,"J":500,"K":667,"L":611,"M":833,"N":722,"O":778,"P":667,"Q":778,"R":722,"S":667,"T":611,"U":722,"V":667,"W":944,"X":667,"Y":611,"Z":611,"[":333,"\":278,"]":333,"^":469,"_":556,"`":333,"a":556,"b":556,"c":500,"d":556,"e":556,"f":278,"g":556,"h":556,"i":222,"j":222,"k":500,"l":222,"m":833,"n":556,"o":556,"p":556,"q":556,"r":333,"s":500,"t":278,"u":556,"v":500,"w":722,"x":500,"y":500,"z":500,"{":334,"|":260,"}":334,"~":584,"€":556,"":556,"‚":278,"ƒ":556,"„":556,"…":556,"†":556,"‡":556,"ˆ":556,"‰":556,"Š":667,"‹":500,"Œ":778,"":556,"Ž":611,"":556,"":556,"‘":556,"’":556,"“":556,"”":556,"•":556,"–":556,"—":556,"˜":556,"™":833,"š":500,"›":500,"œ":556,"":556,"ž":500,"Ÿ":500,"¡":278,"¢":556,"£":556,"¤":556,"¥":556,"¦":260,"§":556,"¨":333,"©":737,"ª":370,"«":556,"¬":584,"®":737,"¯":333,"°":400,"±":584,"²":338,"³":338,"´":333,"µ":556,"":667,"·":278,"¸":333,"¹":338,"º":370,"»":556,"¼":833,"½":833,"¾":833,"¿":556,"À":667,"Á":667,"Â":667,"Ã":667,"Ä":667,"Å":667,"Æ":944,"Ç":722,"È":667,"É":667,"Ê":667,"Ë":667,"Ì":278,"Í":278,"Î":278,"Ï":278,"Ð":722,"Ñ":722,"Ò":778,"Ó":778,"Ô":778,"Õ":778,"Ö":778,"×":584,"Ø":778,"Ù":722,"Ú":722,"Û":722,"Ü":722,"Ý":667,"Þ":667,"ß":500,"à":556,"á":556,"â":556,"ã":556,"ä":556,"å":556,"æ":778,"ç":500,"è":556,"é":556,"ê":556,"ë":556,"ì":222,"í":222,"î":222,"ï":222,"ð":556,"ñ":556,"ò":556,"ó":556,"ô":556,"õ":556,"ö":556,"÷":584,"ø":556,"ù":556,"ú":556,"û":556,"ü":556,"ý":500,"þ":556,"ÿ":500}

View File

@ -0,0 +1 @@
{" ":278,"!":333,"\"":424,"#":611,"$":611,"%":944,"&":722,"' ":278,"":333,"":333,"*":444,"+":611,",":278,".":278,"-":333,"/":278,"":611,"":611,"":611,"":611,"":611,"":611,"":611,"":611,"":611,"":611,":":278,";":278,"<":611,"=":611,">":611,"?":611,"@":1015,"A":722,"B":722,"C":778,"D":778,"E":722,"F":667,"G":833,"H":778,"I":333,"J":556,"K":722,"L":667,"M":889,"N":778,"O":833,"P":722,"Q":833,"R":778,"S":722,"T":667,"U":778,"V":722,"W":1000,"X":722,"Y":667,"Z":667,"[":333,"\":278,"]":333,"^":508,"_":611,"`":333,"a":611,"b":611,"c":556,"d":611,"e":611,"f":333,"g":611,"h":611,"i":278,"j":278,"k":556,"l":278,"m":889,"n":611,"o":611,"p":611,"q":611,"r":389,"s":556,"t":333,"u":611,"v":556,"w":778,"x":556,"y":556,"z":556,"{":389,"|":303,"}":389,"~":611,"€":611,"":611,"‚":278,"ƒ":611,"„":611,"…":611,"†":611,"‡":611,"ˆ":611,"‰":611,"Š":722,"‹":556,"Œ":833,"":611,"Ž":667,"":611,"":611,"‘":611,"’":611,"“":611,"”":611,"•":611,"–":611,"—":611,"˜":611,"™":889,"š":556,"›":556,"œ":611,"":611,"ž":556,"Ÿ":556,"¡":333,"¢":611,"£":611,"¤":611,"¥":611,"¦":303,"§":611,"¨":389,"©":737,"ª":401,"«":611,"¬":611,"®":737,"¯":389,"°":444,"±":611,"²":382,"³":382,"´":389,"µ":611,"":722,"·":278,"¸":333,"¹":382,"º":401,"»":611,"¼":944,"½":944,"¾":944,"¿":611,"À":722,"Á":722,"Â":722,"Ã":722,"Ä":722,"Å":722,"Æ":1000,"Ç":778,"È":722,"É":722,"Ê":722,"Ë":722,"Ì":333,"Í":333,"Î":333,"Ï":333,"Ð":778,"Ñ":778,"Ò":833,"Ó":833,"Ô":833,"Õ":833,"Ö":833,"×":611,"Ø":833,"Ù":778,"Ú":778,"Û":778,"Ü":778,"Ý":722,"Þ":722,"ß":556,"à":611,"á":611,"â":611,"ã":611,"ä":611,"å":611,"æ":889,"ç":556,"è":611,"é":611,"ê":611,"ë":611,"ì":278,"í":278,"î":278,"ï":278,"ð":611,"ñ":611,"ò":611,"ó":611,"ô":611,"õ":611,"ö":611,"÷":611,"ø":611,"ù":611,"ú":611,"û":611,"ü":611,"ý":556,"þ":611,"ÿ":556}

1822
lib/fpdf/fpdf.php Normal file

File diff suppressed because it is too large Load Diff