Files
flowmanager/include/include_functions.php
2025-10-09 16:20:58 +02:00

320 lines
8.6 KiB
PHP

<?php
/**
* FlowManager Helper Functions
*
* Bevat functies en standaardinstellingen voor het beheren van Node-RED flows.
* Inclusief:
* - Deploy van flows
* - Versiebeheer
* - Template rendering
* - Omgevingen ophalen
*/
// ------------------------------------------------------
// *** DEFAULT SETTINGS FLOW ***
// ------------------------------------------------------
// --- Parameters ophalen of defaults ---
$parameters = [
'assetId' => $_POST['assetId'] ?? '',
'assetName' => $_POST['assetName'] ?? '',
'param1' => $_POST['param1'] ?? '',
'param2' => $_POST['param2'] ?? ''
];
// Node-RED omgevingen
$envFile = __DIR__ . '/../settings/environments.json';
$environments = getNodeRedEnvironments($envFile);
$selectedEnv = $_POST['environment'] ?? '';
// Alert template-versie
$newVersionAlert = checkNewTemplateVersionAlert($templatePath, $deployDir);
// Overzicht deploys
$deploys = getDeploysWithVersions($deployDir);
// Init variabelen
$deployResponse = '';
$newFileName = '';
$envUrl = '';
$successMessage = '';
// Deploy verwerken
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['deploy'])) {
$deployResult = deployFlow($parameters, $templatePath, $deployDir, $environments, $selectedEnv);
if ($deployResult['success']) {
$deployResponse = $deployResult['response'];
$newFileName = $deployResult['file'];
$envUrl = $deployResult['envUrl'];
$successMessage = renderAlert($deployResult['message'], 'success');
} else {
$successMessage = renderAlert($deployResult['message'], 'danger');
}
}
// ------------------------------------------------------
// *** HELPERS ***
// ------------------------------------------------------
/**
* Verkrijg een overzicht van alle Node-RED omgevingen
*
* @param string $envFile Pad naar JSON-bestand met omgevingen
* @return array
*/
function getNodeRedEnvironments(string $envFile): array
{
$json = @file_get_contents($envFile);
if (!$json) return [];
$data = json_decode($json, true);
return is_array($data) ? $data : [];
}
/**
* Vind alle versioned JSON-bestanden in een directory
*
* @param string $dir
* @return array
*/
function findVersionedJsonFilesInDir(string $dir): array
{
$matches = [];
foreach (scandir($dir) as $file) {
if (preg_match('/^version\d+_\d{12}\.json$/', $file)) {
$matches[] = ['name' => $file];
}
}
usort($matches, fn($a, $b) => strcmp($a['name'], $b['name']));
return $matches;
}
/**
* Vind het laatst gedeployde bestand
*
* @param string $dir
* @return string|null
*/
function findLatestDeployFile(string $dir): ?string
{
$files = findVersionedJsonFilesInDir($dir);
return !empty($files) ? end($files)['name'] : null;
}
/**
* Haal versie uit een JSON-bestand
*
* @param string $filePath
* @return int
*/
function getVersionFromJson(string $filePath): int
{
if (!file_exists($filePath)) return 0;
$json = json_decode(file_get_contents($filePath), true);
return $json[0]['version'] ?? 0;
}
/**
* Haal versie uit een template
*
* @param string $templatePath
* @return int
*/
function getVersionFromTemplate(string $templatePath): int
{
if (!file_exists($templatePath)) return 0;
preg_match('/"version"\s*:\s*(\d+)/', file_get_contents($templatePath), $m);
return $m[1] ?? 0;
}
/**
* Controleer of de template een hogere versie heeft dan de laatste deploy
*
* @param string $templatePath
* @param string $deployDir
* @return string|null
*/
function checkNewTemplateVersionAlert(string $templatePath, string $deployDir): ?string
{
$templateVersion = getVersionFromTemplate($templatePath);
$latestDeployFile = findLatestDeployFile($deployDir);
$latestVersion = $latestDeployFile ? getVersionFromJson($deployDir . '/' . $latestDeployFile) : 0;
if ($templateVersion > $latestVersion) {
return "<div class='alert alert-warning'>
Nieuwe template-versie beschikbaar!
(Template v$templateVersion &gt; Laatste deploy v$latestVersion)
</div>";
}
return null;
}
/**
* Genereer de bestandsnaam voor een nieuwe deploy
*
* @param int $version
* @return string
*/
function generateNextDeployFileName(int $version): string
{
return "version{$version}_" . date('YmdHi') . ".json";
}
/**
* Render een template met placeholders
*
* @param string $templatePath
* @param array $placeholders
* @return string
*/
function renderTemplate(string $templatePath, array $placeholders): string
{
$content = file_get_contents($templatePath);
foreach ($placeholders as $key => $value) {
$content = str_replace("{{{$key}}}", $value, $content);
}
return $content;
}
/**
* Render een standaard alert
*
* @param string $message
* @param string $type
* @return string
*/
function renderAlert(string $message, string $type = 'info'): string
{
return "<div class='alert alert-{$type}'>$message</div>";
}
/**
* Verkrijg een overzicht van alle deploys inclusief versies
*
* @param string $dir
* @return array
*/
function getDeploysWithVersions(string $dir): array
{
$files = findVersionedJsonFilesInDir($dir);
return array_map(function ($f) use ($dir) {
return [
'name' => $f['name'],
'version' => getVersionFromJson($dir . '/' . $f['name'])
];
}, array_reverse($files));
}
// ------------------------------------------------------
// *** DEPLOY FUNCTIES ***
// ------------------------------------------------------
/**
* Deploy een JSON-flowbestand naar een Node-RED URL via POST
*
* @param string $flowPath Pad naar flow JSON
* @param string $url Node-RED URL
* @return string HTTP status code of foutmelding
*/
function deployFlowToUrl(string $flowPath, string $url): string
{
if (!file_exists($flowPath)) {
return '<div class="alert alert-danger" role="alert">
<strong>Fout:</strong> Flowbestand niet gevonden: ' . htmlspecialchars($flowPath) . '
</div>';
}
$flowJson = file_get_contents($flowPath);
$ch = curl_init(rtrim($url, '/') . '/flows');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_POSTFIELDS => $flowJson,
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return $httpCode;
}
/**
* Deploy een flow naar een geselecteerde Node-RED omgeving
*
* @param array $parameters Asset parameters
* @param string $templatePath Pad naar template JSON
* @param string $deployDir Deploy directory
* @param array $environments Beschikbare Node-RED omgevingen
* @param string $selectedEnv Geselecteerde omgeving (IP)
* @return array Resultaat van de deploy
*/
function deployFlow(array $parameters, string $templatePath, string $deployDir, array $environments, string $selectedEnv): array
{
$result = [
'success' => false,
'message' => '',
'file' => null,
'envUrl' => null,
'response' => null
];
if (empty($selectedEnv)) {
$result['message'] = 'Geen omgeving geselecteerd!';
return $result;
}
// Template-versie ophalen
$templateVersion = getVersionFromTemplate($templatePath);
// URL van geselecteerde omgeving
$envUrl = '';
foreach ($environments as $env) {
if (($env['ip'] ?? '') === $selectedEnv) {
$envUrl = $env['ip'];
break;
}
}
if (!$envUrl) {
$result['message'] = 'Omgeving niet gevonden of URL ontbreekt!';
return $result;
}
// Placeholders invullen
$placeholders = [
'id' => $parameters['assetId'] ?? '',
'name' => $parameters['assetName'] ?? '',
'version' => $templateVersion,
'param1' => $parameters['param1'] ?? '',
'param2' => $parameters['param2'] ?? '',
'ip' => $envUrl
];
// Template renderen en deploy-bestand schrijven
$flowJson = renderTemplate($templatePath, $placeholders);
$newFileName = generateNextDeployFileName($templateVersion);
$deployFile = $deployDir . '/' . $newFileName;
file_put_contents($deployFile, $flowJson);
// Deploy naar Node-RED uitvoeren
$deployResponse = deployFlowToUrl($deployFile, $envUrl);
$result['success'] = true;
$result['message'] = "Nieuwe versie <strong>$newFileName</strong> gedeployed naar <strong>$envUrl</strong>!";
$result['file'] = $newFileName;
$result['envUrl'] = $envUrl;
$result['response'] = $deployResponse;
return $result;
}