OpenNIT

Quelltext des aktuellen Standes

Fassung 1.1.1

send-notifications.php

5 KB
<?php
// Verarbeitet E-Mail-Benachrichtigungen
//
// Dieses Script sollte regelmaessig per Cron ausgefuehrt werden (z.B. alle 5 Minuten):
//   */5 * * * * /usr/bin/php /pfad/zu/bin/send-notifications.php >> /pfad/zu/storage/logs/send-notifications.log 2>&1
//
// Es fuehrt vier Aufgaben aus:
//   1. Erstellt Benachrichtigungen fuer heute faellige Reviews
//   2. Prueft Vertrags-Kuendigungserinnerungen
//   3. Prueft ob ein Software-Update verfuegbar ist und benachrichtigt Admins
//   4. Verarbeitet die Benachrichtigungs-Queue (sendet E-Mails)

require_once __DIR__ . '/../vendor/autoload.php';
require_once __DIR__ . '/../bootstrap.php';

use OpenNIT\Core\Database;
use OpenNIT\Audit\AuditLogger;
use OpenNIT\Notifications\NotificationManager;
use OpenNIT\Content\UpdateManager;
use OpenNIT\Security\CredentialCrypto;

// Umgebungsvariablen aus .env laden (identisch zu public/index.php)
$dotenv = Dotenv\Dotenv::createImmutable(dirname(__DIR__));
$dotenv->load();

// Datenbankkonfiguration laden (config/app.php hat keinen 'database'-Key)
$dbConfig = require __DIR__ . '/../config/database.php';
$runtimeConfig = [];
$runtimeFile = __DIR__ . '/../config/runtime.php';
if (file_exists($runtimeFile)) {
    $runtimeConfig = include $runtimeFile;
}

// Zeitzone aus Konfiguration setzen
$timezone = $runtimeConfig['app']['timezone'] ?? 'Europe/Berlin';
date_default_timezone_set($timezone);

// Datenbank-Verbindung
$db = new Database($dbConfig);

// Audit-Logger (vereinfacht fuer CLI)
$auditLogger = new AuditLogger($db);

// Versand-Konfiguration (basic, Graph oder XOAUTH2 – über die Factory)
$smtpConfig = \OpenNIT\Mail\MailTransportFactory::globalSenderConfig(
    $runtimeConfig,
    $_ENV['APP_KEY'] ?? '',
    dirname(__DIR__) . '/storage/cache'
);

$nm = new NotificationManager($db, $auditLogger, $smtpConfig);

/**
 * Protokolliert einen Cronjob-Lauf in der Datenbank
 */
function trackCronjob(Database $db, string $jobName, callable $callback): void
{
    $startedAt = date('Y-m-d H:i:s');

    // Laufenden Eintrag erstellen
    try {
        $runId = $db->insert('cronjob_runs', [
            'job_name' => $jobName,
            'started_at' => $startedAt,
            'status' => 'running',
        ]);
    } catch (\Throwable $e) {
        // Tracking nicht verfügbar (z.B. Migration noch nicht ausgeführt) - Job trotzdem starten
        echo date('Y-m-d H:i:s') . " - [WARNUNG] Cronjob-Tracking fehlgeschlagen ({$jobName}): " . $e->getMessage() . "\n";
        $callback();
        return;
    }

    try {
        $result = $callback();
        $message = is_string($result) ? $result : null;
        $count = is_int($result) ? $result : 0;

        $db->update('cronjob_runs', [
            'finished_at' => date('Y-m-d H:i:s'),
            'status' => 'success',
            'message' => $message,
            'items_processed' => $count,
        ], 'id = ?', [$runId]);

        if ($count > 0) {
            echo date('Y-m-d H:i:s') . " - {$jobName}: {$count} verarbeitet\n";
        }
    } catch (\Throwable $e) {
        $db->update('cronjob_runs', [
            'finished_at' => date('Y-m-d H:i:s'),
            'status' => 'error',
            'message' => substr($e->getMessage(), 0, 1000),
        ], 'id = ?', [$runId]);

        echo date('Y-m-d H:i:s') . " - {$jobName} FEHLER: " . $e->getMessage() . "\n";
    }
}

// 1. Review-Benachrichtigungen erstellen
trackCronjob($db, 'review_notifications', function () use ($nm) {
    return $nm->notifyDueReviews();
});

// 2. Vertrags-Kuendigungserinnerungen pruefen
trackCronjob($db, 'contract_reminders', function () use ($nm) {
    return $nm->notifyExpiringContracts();
});

// 2b. SSL-Zertifikat-Ablauferinnerungen (5 Tage vor Ablauf)
trackCronjob($db, 'ssl_reminder', function () use ($nm) {
    return $nm->notifyExpiringSslCertificates();
});

// 3. Update-Pruefung: Admins benachrichtigen wenn neue Version verfuegbar
trackCronjob($db, 'update_check', function () use ($db, $auditLogger, $nm) {
    $updateManager = new UpdateManager($db, $auditLogger, (string)($runtimeConfig['update']['channel'] ?? 'stable'));
    $result = $updateManager->checkForUpdates();

    if (!$result['has_update'] || empty($result['latest_sha'])) {
        return 0;
    }

    $latestSha = $result['latest_sha'];
    $commitMessage = $result['latest_commit']['message'] ?? null;

    return $nm->notifyAdminsUpdateAvailable($latestSha, $commitMessage);
});

// 3b. Leihgeräte-Überfälligkeitserinnerungen (täglich, einmalig pro Leihvorgang)
trackCronjob($db, 'loan_overdue_reminder', function () use ($nm) {
    return $nm->notifyOverdueLoanDevices();
});

// 3c. To-Do-Fälligkeitserinnerungen (täglich, einen Tag vor Fälligkeit)
trackCronjob($db, 'todo_due_reminder', function () use ($nm) {
    return $nm->notifyDueTodos();
});

// 4. Queue verarbeiten
trackCronjob($db, 'email_queue', function () use ($nm) {
    $result = $nm->processQueue();
    $total = $result['sent'] + $result['failed'];
    if ($result['failed'] > 0) {
        echo date('Y-m-d H:i:s') . " - Queue: {$result['sent']} gesendet, {$result['failed']} fehlgeschlagen\n";
    }
    return $total;
});