Files
ms1inscription-v5/php/inc_fx_kc_qr.php
stephan 3e3a0f1de7 Add static sync functionality and update UI for development tools
This commit introduces the `fxAdminStaticSyncAllowed` function to control access to static database synchronization tools, ensuring only authorized users in development and pre-production environments can access them. The UI is updated to display a new section for these tools in the admin interface, enhancing the overall user experience and access management for development tasks. Additionally, the `.gitignore` file is updated to exclude the `/output/` directory from version control.
2026-06-22 14:08:16 -04:00

156 lines
5.2 KiB
PHP

<?php
require_once __DIR__ . '/../libs/phpqrcode-master/qrlib.php';
/**
* Logo MS1 au centre du QR (carré noir, texte blanc).
*/
function fxKcQrCreateLogoImage($intSize)
{
$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 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);
$strDir = dirname($strOutputFile);
if (!is_dir($strDir)) {
mkdir($strDir, 0755, true);
}
QRcode::png(
$strUrl,
$strOutputFile,
QR_ECLEVEL_H,
$intModuleSize,
2
);
if ($blnWithLogo) {
fxKcQrOverlayLogo($strOutputFile);
}
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'),
];
}