243 lines
6.8 KiB
PHP
243 lines
6.8 KiB
PHP
<?php
|
||
/**
|
||
* MSIN-4485 — Impression dossard PDF (demi-lettre, fond image + overlays).
|
||
* Module isolé : hors panier / hors hub promoteur.
|
||
*/
|
||
|
||
define('MSIN_DOSSARD_PRINT_PERM', 'inscriptions_gestion.dossard_print');
|
||
|
||
/** Largeur / hauteur demi-lettre (pouces → mm). */
|
||
function fxDossardPrintPageSizeMm()
|
||
{
|
||
return array(5.5 * 25.4, 8.5 * 25.4);
|
||
}
|
||
|
||
/** Dossier des fonds PNG/JPG. */
|
||
function fxDossardPrintTemplatesDir()
|
||
{
|
||
return dirname(__DIR__) . '/assets/dossard_templates';
|
||
}
|
||
|
||
/**
|
||
* Fond à utiliser : eve_{id}.png|jpg si présent, sinon default.png|jpg.
|
||
*
|
||
* @return string|null chemin absolu
|
||
*/
|
||
function fxDossardPrintResolveTemplatePath($intEveId)
|
||
{
|
||
$strDir = fxDossardPrintTemplatesDir();
|
||
$intEveId = intval($intEveId);
|
||
$arrCandidates = array();
|
||
if ($intEveId > 0) {
|
||
$arrCandidates[] = $strDir . '/eve_' . $intEveId . '.png';
|
||
$arrCandidates[] = $strDir . '/eve_' . $intEveId . '.jpg';
|
||
$arrCandidates[] = $strDir . '/eve_' . $intEveId . '.jpeg';
|
||
}
|
||
$arrCandidates[] = $strDir . '/default.png';
|
||
$arrCandidates[] = $strDir . '/default.jpg';
|
||
$arrCandidates[] = $strDir . '/default.jpeg';
|
||
|
||
foreach ($arrCandidates as $strPath) {
|
||
if (is_file($strPath)) {
|
||
return $strPath;
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
/** Texte FPDF (core fonts = Windows-1252). */
|
||
function fxDossardPrintPdfText($str)
|
||
{
|
||
$str = (string)$str;
|
||
if (function_exists('iconv')) {
|
||
$strConverted = @iconv('UTF-8', 'Windows-1252//TRANSLIT', $str);
|
||
if ($strConverted !== false) {
|
||
return $strConverted;
|
||
}
|
||
}
|
||
|
||
return utf8_decode($str);
|
||
}
|
||
|
||
/**
|
||
* MSIN-4485 — Droit impression dossard (hors kit total si perm_grants_all = 0).
|
||
*/
|
||
function fxDossardPrintCan($intComId, $intEveId)
|
||
{
|
||
if (!function_exists('fxEveAccesHasPermission')) {
|
||
require_once __DIR__ . '/inc_fx_eve_acces.php';
|
||
}
|
||
|
||
return fxEveAccesHasPermission(intval($intComId), intval($intEveId), MSIN_DOSSARD_PRINT_PERM);
|
||
}
|
||
|
||
/**
|
||
* Charge participant + vérifie appartenance à l'événement.
|
||
*
|
||
* @return array|null
|
||
*/
|
||
function fxDossardPrintLoadParticipant($intParId, $intEveId)
|
||
{
|
||
global $objDatabase;
|
||
|
||
$intParId = intval($intParId);
|
||
$intEveId = intval($intEveId);
|
||
if ($intParId <= 0 || $intEveId <= 0) {
|
||
return null;
|
||
}
|
||
|
||
$sql = 'SELECT p.par_id, p.par_prenom, p.par_nom, p.no_bib, p.eve_id, p.epr_id, p.pec_id,
|
||
e.pec_id_original, e.pec_actif, e.is_cancelled
|
||
FROM resultats_participants p
|
||
INNER JOIN resultats_epreuves_commandees e
|
||
ON e.pec_id_original = p.pec_id AND e.epr_id = p.epr_id
|
||
WHERE p.par_id = ' . $intParId . '
|
||
AND p.eve_id = ' . $intEveId . '
|
||
LIMIT 1';
|
||
|
||
$row = $objDatabase->fxGetRow($sql);
|
||
|
||
return ($row === null || $row === false) ? null : $row;
|
||
}
|
||
|
||
/**
|
||
* URL à encoder dans le QR (résultats événement — même modèle que kc.php).
|
||
*/
|
||
function fxDossardPrintQrUrl($intEveId)
|
||
{
|
||
if (!function_exists('fxKcEveResultatsQrUrl')) {
|
||
require_once __DIR__ . '/inc_fx_eve_extra.php';
|
||
}
|
||
|
||
return fxKcEveResultatsQrUrl(intval($intEveId));
|
||
}
|
||
|
||
/**
|
||
* PNG temporaire du QR (sans logo pour rester net dans la petite case).
|
||
*
|
||
* @return string|false chemin fichier temp
|
||
*/
|
||
function fxDossardPrintBuildQrTempFile($intEveId)
|
||
{
|
||
require_once __DIR__ . '/../libs/phpqrcode-master/qrlib.php';
|
||
|
||
$strUrl = fxDossardPrintQrUrl($intEveId);
|
||
if ($strUrl === '') {
|
||
return false;
|
||
}
|
||
|
||
$strTmp = tempnam(sys_get_temp_dir(), 'ms1dossardqr_');
|
||
if ($strTmp === false) {
|
||
return false;
|
||
}
|
||
// QRcode::png exige souvent une extension .png
|
||
$strPng = $strTmp . '.png';
|
||
@unlink($strTmp);
|
||
|
||
QRcode::png($strUrl, $strPng, QR_ECLEVEL_M, 6, 1);
|
||
if (!is_file($strPng)) {
|
||
return false;
|
||
}
|
||
|
||
return $strPng;
|
||
}
|
||
|
||
/**
|
||
* Coordonnées overlays (mm) — ajustables selon le fond.
|
||
* Demi-lettre 139.7 × 215.9 mm.
|
||
*
|
||
* @return array<string,mixed>
|
||
*/
|
||
function fxDossardPrintLayout()
|
||
{
|
||
$arrSize = fxDossardPrintPageSizeMm();
|
||
$fltW = $arrSize[0];
|
||
$fltH = $arrSize[1];
|
||
|
||
return array(
|
||
'page_w' => $fltW,
|
||
'page_h' => $fltH,
|
||
// Numéro centré dans la zone blanche centrale
|
||
'bib_y' => 88,
|
||
'bib_font' => 64,
|
||
// Nom sous le numéro
|
||
'name_y' => 128,
|
||
'name_font' => 12,
|
||
// Case QR bas-droite (repères du template)
|
||
'qr_x' => 100.5,
|
||
'qr_y' => 172.5,
|
||
'qr_size' => 28.5,
|
||
);
|
||
}
|
||
|
||
/**
|
||
* Génère et envoie le PDF (exit).
|
||
*
|
||
* @param array $arrRow ligne fxDossardPrintLoadParticipant
|
||
*/
|
||
function fxDossardPrintOutputPdf($arrRow)
|
||
{
|
||
$intEveId = intval($arrRow['eve_id'] ?? 0);
|
||
$strTemplate = fxDossardPrintResolveTemplatePath($intEveId);
|
||
if ($strTemplate === null) {
|
||
http_response_code(500);
|
||
header('Content-Type: text/plain; charset=utf-8');
|
||
echo 'Template dossard introuvable (assets/dossard_templates/default.png).';
|
||
exit;
|
||
}
|
||
|
||
$strDocRoot = $_SERVER['DOCUMENT_ROOT'] ?? dirname(__DIR__);
|
||
require_once $strDocRoot . '/fpdf182/fpdf.php';
|
||
|
||
$arrLayout = fxDossardPrintLayout();
|
||
$strBib = trim((string)($arrRow['no_bib'] ?? ''));
|
||
if ($strBib === '' || $strBib === '0') {
|
||
$strBib = '—';
|
||
}
|
||
$strPrenom = trim(function_exists('fxUnescape') ? fxUnescape($arrRow['par_prenom'] ?? '') : (string)($arrRow['par_prenom'] ?? ''));
|
||
$strNom = trim(function_exists('fxUnescape') ? fxUnescape($arrRow['par_nom'] ?? '') : (string)($arrRow['par_nom'] ?? ''));
|
||
$strName = trim($strPrenom . ' ' . $strNom);
|
||
|
||
$strQrFile = fxDossardPrintBuildQrTempFile($intEveId);
|
||
|
||
$pdf = new FPDF('P', 'mm', array($arrLayout['page_w'], $arrLayout['page_h']));
|
||
$pdf->SetAutoPageBreak(false);
|
||
$pdf->SetMargins(0, 0, 0);
|
||
$pdf->AddPage();
|
||
|
||
// Fond pleine page
|
||
$pdf->Image($strTemplate, 0, 0, $arrLayout['page_w'], $arrLayout['page_h']);
|
||
|
||
// Numéro de dossard
|
||
$pdf->SetTextColor(0, 0, 0);
|
||
$pdf->SetFont('Helvetica', 'B', intval($arrLayout['bib_font']));
|
||
$pdf->SetXY(8, $arrLayout['bib_y']);
|
||
$pdf->Cell($arrLayout['page_w'] - 16, 22, fxDossardPrintPdfText($strBib), 0, 0, 'C');
|
||
|
||
// Nom
|
||
if ($strName !== '') {
|
||
$pdf->SetFont('Helvetica', 'B', intval($arrLayout['name_font']));
|
||
$pdf->SetXY(10, $arrLayout['name_y']);
|
||
$pdf->Cell($arrLayout['page_w'] - 20, 8, fxDossardPrintPdfText($strName), 0, 0, 'C');
|
||
}
|
||
|
||
// QR résultats
|
||
if ($strQrFile !== false) {
|
||
$pdf->Image(
|
||
$strQrFile,
|
||
$arrLayout['qr_x'],
|
||
$arrLayout['qr_y'],
|
||
$arrLayout['qr_size'],
|
||
$arrLayout['qr_size']
|
||
);
|
||
@unlink($strQrFile);
|
||
}
|
||
|
||
$strSafeBib = preg_replace('/[^a-zA-Z0-9_-]+/', '-', $strBib);
|
||
$strFilename = 'dossard-' . $strSafeBib . '-par' . intval($arrRow['par_id']) . '.pdf';
|
||
|
||
$pdf->Output('I', $strFilename);
|
||
exit;
|
||
}
|