Files
ms1inscription-v5/php/inc_fx_kc_qr.php

251 lines
8.1 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
require_once __DIR__ . '/../libs/phpqrcode-master/qrlib.php';
/**
* Chemin du logo MS1 pour le centre des QR key_chain.
*/
function fxKcQrLogoPath()
{
return __DIR__ . '/../images/ms1-kc-logo.png';
}
/**
* Charge et redimensionne le logo PNG (carré de sortie $intSize).
* Repli : dessin texte si le fichier est absent.
*/
function fxKcQrCreateLogoImage($intSize)
{
$intSize = max(24, (int) $intSize);
$strLogoPath = fxKcQrLogoPath();
if (is_file($strLogoPath)) {
$imgSrc = @imagecreatefrompng($strLogoPath);
if ($imgSrc !== false) {
$intSrcW = imagesx($imgSrc);
$intSrcH = imagesy($imgSrc);
$img = imagecreatetruecolor($intSize, $intSize);
imagealphablending($img, false);
imagesavealpha($img, true);
$colTransparent = imagecolorallocatealpha($img, 0, 0, 0, 127);
imagefilledrectangle($img, 0, 0, $intSize, $intSize, $colTransparent);
imagealphablending($img, true);
// Conserve le ratio (158×180) dans le carré cible.
$fltScale = min($intSize / max(1, $intSrcW), $intSize / max(1, $intSrcH));
$intDstW = max(1, (int) round($intSrcW * $fltScale));
$intDstH = max(1, (int) round($intSrcH * $fltScale));
$intDstX = (int) floor(($intSize - $intDstW) / 2);
$intDstY = (int) floor(($intSize - $intDstH) / 2);
imagecopyresampled(
$img,
$imgSrc,
$intDstX,
$intDstY,
0,
0,
$intDstW,
$intDstH,
$intSrcW,
$intSrcH
);
imagedestroy($imgSrc);
return $img;
}
}
// Repli : dessin texte (si PNG manquant).
$img = imagecreatetruecolor($intSize, $intSize);
imagealphablending($img, true);
imagesavealpha($img, true);
$colBlack = imagecolorallocate($img, 0, 0, 0);
$colWhite = imagecolorallocate($img, 255, 255, 255);
imagefilledrectangle($img, 0, 0, $intSize, $intSize, $colBlack);
$strFont = __DIR__ . '/../fonts/arial.ttf';
if (!is_file($strFont)) {
$strFont = 'C:/Windows/Fonts/arial.ttf';
}
if (is_file($strFont)) {
$intLeftX = (int) round($intSize * 0.12);
$intRightX = (int) round($intSize * 0.52);
$intFontSmall = max(8, (int) round($intSize * 0.16));
$intFontBig = max(12, (int) round($intSize * 0.42));
imagettftext($img, $intFontSmall, 0, $intLeftX, (int) round($intSize * 0.30), $colWhite, $strFont, 'm');
imagettftext($img, (int) round($intFontSmall * 0.55), 0, $intLeftX + (int) round($intSize * 0.04), (int) round($intSize * 0.46), $colWhite, $strFont, chr(183));
imagettftext($img, $intFontSmall, 0, $intLeftX, (int) round($intSize * 0.62), $colWhite, $strFont, 's');
imagettftext($img, $intFontBig, 0, $intRightX, (int) round($intSize * 0.68), $colWhite, $strFont, '1');
} else {
imagestring($img, 5, (int) round($intSize * 0.18), (int) round($intSize * 0.28), 'm.s', $colWhite);
imagestring($img, 5, (int) round($intSize * 0.55), (int) round($intSize * 0.40), '1', $colWhite);
}
return $img;
}
/**
* Superpose le logo au centre d'un PNG QR existant.
*/
function fxKcQrOverlayLogo($strQrPath, $fltLogoRatio = 0.22)
{
$imgQr = imagecreatefrompng($strQrPath);
if ($imgQr === false) {
return false;
}
$intQrW = imagesx($imgQr);
$intQrH = imagesy($imgQr);
$intLogoSize = (int) max(24, round(min($intQrW, $intQrH) * $fltLogoRatio));
$intPad = (int) max(2, round($intLogoSize * 0.08));
$imgLogo = fxKcQrCreateLogoImage($intLogoSize);
$imgBlock = imagecreatetruecolor($intLogoSize + ($intPad * 2), $intLogoSize + ($intPad * 2));
$colWhite = imagecolorallocate($imgBlock, 255, 255, 255);
imagefilledrectangle($imgBlock, 0, 0, $intLogoSize + ($intPad * 2), $intLogoSize + ($intPad * 2), $colWhite);
imagecopy($imgBlock, $imgLogo, $intPad, $intPad, 0, 0, $intLogoSize, $intLogoSize);
$intX = (int) floor(($intQrW - $intLogoSize - ($intPad * 2)) / 2);
$intY = (int) floor(($intQrH - $intLogoSize - ($intPad * 2)) / 2);
imagecopy($imgQr, $imgBlock, $intX, $intY, 0, 0, $intLogoSize + ($intPad * 2), $intLogoSize + ($intPad * 2));
imagepng($imgQr, $strQrPath, 0);
imagedestroy($imgQr);
imagedestroy($imgLogo);
imagedestroy($imgBlock);
return true;
}
/**
* Génère un PNG QR pour une URL quelconque (niveau H, logo optionnel).
* MSIN-3487 — réutilisé key_chain + QR résultats événement.
*
* @param string $strUrl
* @param string $strOutputFile
* @param int $intModuleSize
* @param bool $blnWithLogo
* @return string Chemin du fichier généré
*/
function fxKcQrGeneratePngFromUrl($strUrl, $strOutputFile, $intModuleSize = 18, $blnWithLogo = true)
{
$strDir = dirname($strOutputFile);
if (!is_dir($strDir)) {
mkdir($strDir, 0755, true);
}
QRcode::png(
$strUrl,
$strOutputFile,
QR_ECLEVEL_H,
max(4, (int) $intModuleSize),
2
);
if ($blnWithLogo) {
fxKcQrOverlayLogo($strOutputFile);
}
return $strOutputFile;
}
/**
* Génère un PNG QR en mémoire (binaire) pour une URL.
*
* @param string $strUrl
* @param int $intModuleSize
* @param bool $blnWithLogo
* @return string|false
*/
function fxKcQrGeneratePngBinary($strUrl, $intModuleSize = 10, $blnWithLogo = true)
{
$strTmpBase = tempnam(sys_get_temp_dir(), 'kcqr_');
if ($strTmpBase === false) {
return false;
}
@unlink($strTmpBase);
$strTmpPng = $strTmpBase . '.png';
fxKcQrGeneratePngFromUrl($strUrl, $strTmpPng, $intModuleSize, $blnWithLogo);
if (!is_file($strTmpPng)) {
return false;
}
$binPng = file_get_contents($strTmpPng);
@unlink($strTmpPng);
return ($binPng === false || $binPng === '') ? false : $binPng;
}
/**
* Génère un QR key_chain prêt pour l'impression.
*/
function fxKcQrGeneratePng($intParam1, $strBaseUrl, $strOutputFile, $intModuleSize = 18, $blnWithLogo = true)
{
$strUrl = rtrim($strBaseUrl, '/') . '/kc.php?param1=' . intval($intParam1);
fxKcQrGeneratePngFromUrl($strUrl, $strOutputFile, $intModuleSize, $blnWithLogo);
return [
'param1' => intval($intParam1),
'url' => $strUrl,
'file' => $strOutputFile,
];
}
/**
* Génère une série de QR codes key_chain.
*/
function fxKcQrGenerateBatch(array $options)
{
$intStart = intval($options['start'] ?? 500);
$intCount = max(1, intval($options['count'] ?? 100));
$strBaseUrl = rtrim($options['base_url'] ?? 'https://ms1inscription.com', '/');
$strOutputDir = rtrim($options['output_dir'] ?? (__DIR__ . '/../output/kc_qr'), DIRECTORY_SEPARATOR);
$intModuleSize = max(6, intval($options['module_size'] ?? 18));
$blnWithLogo = !empty($options['with_logo']);
if (!is_dir($strOutputDir)) {
mkdir($strOutputDir, 0755, true);
}
$tabGenerated = [];
for ($i = 0; $i < $intCount; $i++) {
$intParam1 = $intStart + $i;
$strFile = $strOutputDir . DIRECTORY_SEPARATOR . 'qr_kc_' . $intParam1 . '.png';
$tabGenerated[] = fxKcQrGeneratePng($intParam1, $strBaseUrl, $strFile, $intModuleSize, $blnWithLogo);
}
$strManifest = $strOutputDir . DIRECTORY_SEPARATOR . 'manifest.csv';
$fh = fopen($strManifest, 'w');
if ($fh !== false) {
fputcsv($fh, ['param1', 'vehicule_no', 'url', 'filename']);
foreach ($tabGenerated as $row) {
$intVehicule = $row['param1'];
if (defined('KEYCHAIN_HTTP_EDIT_SHIFT')) {
$intVehicule = $row['param1'] - KEYCHAIN_HTTP_EDIT_SHIFT;
}
fputcsv($fh, [
$row['param1'],
$intVehicule,
$row['url'],
basename($row['file']),
]);
}
fclose($fh);
}
return [
'output_dir' => $strOutputDir,
'count' => count($tabGenerated),
'start' => $intStart,
'end' => $intStart + $intCount - 1,
'manifest' => $strManifest,
'files' => array_column($tabGenerated, 'file'),
];
}