Files
ms1inscription-v5/php/inc_fx_dossard_print.php

342 lines
9.3 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* MSIN-4485 — Impression dossard PDF (1 participant).
*
* Format FINAL : demi-feuille Lettre coupée sur le 11"
* → papier 8.5" large × 5.5" haut (paysage)
* → PDF page = exactement cette taille
* → fond pleine page + n° / nom / QR alignés
*
* Impression : papier personnalisé 8.5 × 5.5, échelle 100 %, sans « ajuster à la page ».
*/
define('MSIN_DOSSARD_PRINT_PERM', 'inscriptions_gestion.dossard_print');
/**
* Taille page = feuille coupée (pouces → mm).
* Lettre 8.5×11 coupée en 2 sur le 11" → 8.5 × 5.5.
*
* @return array{0:float,1:float} [largeur, hauteur]
*/
function fxDossardPrintPageSizeMm()
{
return array(8.5 * 25.4, 5.5 * 25.4);
}
/** Dossier des fonds JPG/PNG (même ratio 8.5:5.5 recommandé). */
function fxDossardPrintTemplatesDir()
{
return dirname(__DIR__) . '/assets/dossard_templates';
}
/**
* Fond : eve_{id}.jpg|png sinon default.jpg|png.
*
* @return string|null
*/
function fxDossardPrintResolveTemplatePath($intEveId)
{
$strDir = fxDossardPrintTemplatesDir();
$intEveId = intval($intEveId);
$arrCandidates = array();
if ($intEveId > 0) {
$arrCandidates[] = $strDir . '/eve_' . $intEveId . '.jpg';
$arrCandidates[] = $strDir . '/eve_' . $intEveId . '.jpeg';
$arrCandidates[] = $strDir . '/eve_' . $intEveId . '.png';
}
$arrCandidates[] = $strDir . '/default.jpg';
$arrCandidates[] = $strDir . '/default.jpeg';
$arrCandidates[] = $strDir . '/default.png';
foreach ($arrCandidates as $strPath) {
if (is_file($strPath)) {
return $strPath;
}
}
return null;
}
/**
* Type FPDF d'après le fichier réel.
*
* @return string JPG|PNG|GIF|''
*/
function fxDossardPrintImageType($strPath)
{
$arrInfo = @getimagesize($strPath);
if (!is_array($arrInfo) || empty($arrInfo[2])) {
return '';
}
if ((int)$arrInfo[2] === IMAGETYPE_JPEG) {
return 'JPG';
}
if ((int)$arrInfo[2] === IMAGETYPE_PNG) {
return 'PNG';
}
if ((int)$arrInfo[2] === IMAGETYPE_GIF) {
return 'GIF';
}
return '';
}
/** 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;
}
}
if (function_exists('mb_convert_encoding')) {
return (string)mb_convert_encoding($str, 'Windows-1252', 'UTF-8');
}
return $str;
}
/** Droit impression (hors kit total). */
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);
}
/**
* @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;
}
function fxDossardPrintQrUrl($intEveId)
{
if (!function_exists('fxKcEveResultatsQrUrl')) {
require_once __DIR__ . '/inc_fx_eve_extra.php';
}
return fxKcEveResultatsQrUrl(intval($intEveId));
}
/**
* @return string|false chemin PNG 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;
}
$strPng = $strTmp . '.png';
@unlink($strTmp);
QRcode::png($strUrl, $strPng, QR_ECLEVEL_M, 6, 1);
if (!is_file($strPng)) {
return false;
}
return $strPng;
}
/**
* Layout page 8.5" × 5.5" (mm) + overlays.
* N° max dans la zone blanche ; prénom seul, aligné à gauche ; QR bas-droite.
*
* @return array<string,mixed>
*/
function fxDossardPrintLayout()
{
$arrSize = fxDossardPrintPageSizeMm();
$fltW = $arrSize[0]; // 215.9
$fltH = $arrSize[1]; // 139.7
$fltQr = 28.0;
// Zone blanche centrale (hors panneaux comic G/D et case QR)
$fltZoneX = 48;
$fltZoneW = 118;
return array(
'page_w' => $fltW,
'page_h' => $fltH,
'zone_x' => $fltZoneX,
'zone_w' => $fltZoneW,
// N° : police max auto-fit sur zone_w (plafond)
'bib_y' => 38,
'bib_font_max' => 160,
'bib_h' => 48,
// Prénom seul, aligné à gauche sous le n°
'name_y' => 92,
'name_font' => 18,
'qr_size' => $fltQr,
'qr_x' => $fltW - $fltQr - 11.5,
'qr_y' => $fltH - $fltQr - 14.5,
);
}
/**
* Plus grande police Helvetica Bold qui fait tenir $strBib dans $fltMaxW mm.
*
* @param FPDF $pdf
* @param string $strBib
* @param float $fltMaxW
* @param int $intFontMax
* @return int
*/
function fxDossardPrintFitBibFont($pdf, $strBib, $fltMaxW, $intFontMax)
{
$strPdf = fxDossardPrintPdfText($strBib);
$intLo = 24;
$intHi = max($intLo, intval($intFontMax));
$intBest = $intLo;
while ($intLo <= $intHi) {
$intMid = (int)floor(($intLo + $intHi) / 2);
$pdf->SetFont('Helvetica', 'B', $intMid);
$fltW = $pdf->GetStringWidth($strPdf);
if ($fltW <= $fltMaxW) {
$intBest = $intMid;
$intLo = $intMid + 1;
} else {
$intHi = $intMid - 1;
}
}
return $intBest;
}
/**
* Génère et envoie le PDF (exit).
*
* @param array $arrRow
*/
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.jpg).';
exit;
}
$strFpdf = dirname(__DIR__) . '/fpdf182/fpdf.php';
if (!is_file($strFpdf)) {
$strDocRoot = $_SERVER['DOCUMENT_ROOT'] ?? '';
$strFpdf = rtrim((string)$strDocRoot, '/\\') . '/fpdf182/fpdf.php';
}
if (!is_file($strFpdf)) {
http_response_code(500);
header('Content-Type: text/plain; charset=utf-8');
echo 'FPDF introuvable (fpdf182/fpdf.php).';
exit;
}
require_once $strFpdf;
$arrLayout = fxDossardPrintLayout();
$strBib = trim((string)($arrRow['no_bib'] ?? ''));
if ($strBib === '' || $strBib === '0') {
$strBib = '-';
}
// MSIN-4485 — prénom seul, aligné à gauche sous le n°.
$strName = trim(function_exists('fxUnescape') ? fxUnescape($arrRow['par_prenom'] ?? '') : (string)($arrRow['par_prenom'] ?? ''));
$strQrFile = fxDossardPrintBuildQrTempFile($intEveId);
$strTplType = fxDossardPrintImageType($strTemplate);
// Page = feuille coupée 8.5" × 5.5".
// FPDF (_getpagesize) range si w>h ; 'L' remet w=8.5 h=5.5.
$pdf = new FPDF('L', 'mm', array($arrLayout['page_w'], $arrLayout['page_h']));
$pdf->SetAutoPageBreak(false);
$pdf->SetMargins(0, 0, 0);
$pdf->AddPage();
// Fond pleine page — ratio template ≈ 8.5:5.5 → pas de déformation
$pdf->Image(
$strTemplate,
0,
0,
$arrLayout['page_w'],
$arrLayout['page_h'],
$strTplType
);
// Numéro : plus grande police qui tient dans la zone blanche
$pdf->SetTextColor(0, 0, 0);
$intBibFont = fxDossardPrintFitBibFont(
$pdf,
$strBib,
$arrLayout['zone_w'],
$arrLayout['bib_font_max']
);
$pdf->SetFont('Helvetica', 'B', $intBibFont);
$pdf->SetXY($arrLayout['zone_x'], $arrLayout['bib_y']);
$pdf->Cell(
$arrLayout['zone_w'],
$arrLayout['bib_h'],
fxDossardPrintPdfText($strBib),
0,
0,
'C'
);
// Prénom : aligné à gauche (même marge gauche que la zone du n°)
if ($strName !== '') {
$pdf->SetFont('Helvetica', 'B', intval($arrLayout['name_font']));
$pdf->SetXY($arrLayout['zone_x'], $arrLayout['name_y']);
$pdf->Cell($arrLayout['zone_w'], 8, fxDossardPrintPdfText($strName), 0, 0, 'L');
}
// QR dans la case du template
if ($strQrFile !== false) {
$pdf->Image(
$strQrFile,
$arrLayout['qr_x'],
$arrLayout['qr_y'],
$arrLayout['qr_size'],
$arrLayout['qr_size'],
'PNG'
);
@unlink($strQrFile);
}
$strSafeBib = preg_replace('/[^a-zA-Z0-9_-]+/', '-', $strBib);
$strFilename = 'dossard-' . $strSafeBib . '-par' . intval($arrRow['par_id']) . '.pdf';
$pdf->Output('I', $strFilename);
exit;
}