'd.m.Y', 'time_format' => 'H:i'];
$GLOBALS['wp_transients'] = [];
$GLOBALS['wp_http_log'] = [];
$GLOBALS['wp_http_handler'] = null;
$GLOBALS['wp_user'] = ['id' => 0, 'caps' => [], 'name' => '', 'email' => ''];
$GLOBALS['wp_settings_errors'] = [];
$GLOBALS['wp_enqueued'] = [];
$_POST = []; $_GET = []; $_SERVER['REQUEST_METHOD'] = 'GET'; $_SERVER['REMOTE_ADDR'] = '203.0.113.5';
if ($opts !== null) {
$GLOBALS['wp_options']['deskhub_tickets_options'] = array_merge([
'server_url' => 'https://support.example.de', 'api_key' => 'dh_geheimer_schluessel_123', 'min_seconds' => 0, 'rate_limit_per_hour' => 5,
], $opts);
}
}
function run_form_post(array $post): ?string
{
$_POST = $post;
$_SERVER['REQUEST_METHOD'] = 'POST';
try { Deskhub_Tickets_Form::handle_submit(); } catch (WpRedirect $r) { return $r->location; }
return null;
}
/** Holt den Zustand (Fehler/Erfolg), den handle_submit hinterlassen hat, aus der Weiterleitungsadresse. */
function state_from(?string $location): ?array
{
if (!$location || !preg_match('/[?&]dht=([a-f0-9]{16})/', $location, $m)) return null;
return $GLOBALS['wp_transients']['dht_state_' . $m[1]][0] ?? null;
}
function render_form(array $atts = [], ?string $location = null): string
{
$_GET = [];
if ($location && preg_match('/[?&]dht=([a-f0-9]{16})/', $location, $m)) $_GET['dht'] = $m[1];
return Deskhub_Tickets_Form::render_ticket_form($atts);
}
/** Ein gültig aussehendes Formular wie vom Plugin erzeugt: unterschriebene Angaben und Zeitstempel aus der Ausgabe lesen. */
function valid_post(string $html, array $over = []): array
{
preg_match('/name="dht_cfg" value="([^"]*)"/', $html, $c);
preg_match('/name="dht_sig" value="([^"]*)"/', $html, $s);
preg_match('/name="dht_ts" value="([^"]*)"/', $html, $t);
preg_match('/name="dht_back" value="([^"]*)"/', $html, $b);
return array_merge([
'action' => 'deskhub_ticket_submit', 'dht_cfg' => html_entity_decode($c[1] ?? ''), 'dht_sig' => $s[1] ?? '', 'dht_ts' => $t[1] ?? '', 'dht_back' => html_entity_decode($b[1] ?? ''),
'dht_website' => '', 'dht_name' => 'Erika Muster', 'dht_email' => 'erika@kunde.example', 'dht_subject' => 'Rechnung fehlt', 'dht_message' => "Hallo,\nbitte schicken Sie mir die Rechnung.",
], $over);
}
function ok_handler(array &$seen = null): callable
{
return function (string $url, array $args) use (&$seen) {
if (str_contains($url, 'form=1') || str_contains($url, 'topics=1')) return wp_stub_response(422, ['error' => ['code' => 'MISSING_PARAMS', 'message' => 'x']]); // wie ein älterer Server
$seen[] = ['url' => $url, 'args' => $args];
if (($args['method'] ?? 'GET') === 'POST') return wp_stub_response(201, ['number' => '261101-0001', 'status' => 'open']);
return wp_stub_response(200, ['ticket' => ['number' => '261101-0001', 'subject' => 'Rechnung', 'status' => 'answered', 'createdAt' => '2026-11-01 10:00:00', 'updatedAt' => '2026-11-01 11:00:00',
'messages' => [['author' => 'customer', 'message' => 'Hallo ', 'createdAt' => '2026-11-01 10:00:00'], ['author' => 'staff', 'message' => "Erledigt.\nViele Grüße", 'createdAt' => '2026-11-01 11:00:00']]]]);
};
}
// ── Server-Adresse ─────────────────────────────────────────────────────────
reset_wp();
foreach ([
['support.example.de', 'https://support.example.de'],
[' https://support.example.de/ ', 'https://support.example.de'],
['https://example.de/helpdesk/', 'https://example.de/helpdesk'],
['http://127.0.0.1:8080', 'http://127.0.0.1:8080'],
['http://localhost', 'http://localhost'],
] as [$in, $want]) {
$check(Deskhub_Tickets_Client::normalize_url($in) === $want, "Adresse '$in' wird zu '$want'");
}
foreach (['', 'http://support.example.de', 'https://user:pw@example.de', 'https://example.de/?x=1', 'https://example.de/#a', 'ftp://example.de', 'http://localhost.evil.de'] as $bad) {
$check(is_wp_error(Deskhub_Tickets_Client::normalize_url($bad)), "Adresse '$bad' wird abgelehnt");
}
// ── Nicht eingerichtet ──────────────────────────────────────────────────────
reset_wp(['server_url' => '', 'api_key' => '']);
$check(Deskhub_Tickets_Form::render_ticket_form() === '', 'Ohne Einrichtung sieht ein Besucher nichts');
$GLOBALS['wp_user']['caps'] = ['manage_options'];
$check(str_contains(Deskhub_Tickets_Form::render_ticket_form(), 'noch nicht eingerichtet'), 'Ein Administrator sieht den Einrichtungshinweis');
// ── Formular wird angezeigt ─────────────────────────────────────────────────
reset_wp(['consent_text' => 'Ich habe die Datenschutzerklärung gelesen.']);
$html = render_form();
foreach (['name="dht_name"', 'name="dht_email"', 'name="dht_subject"', 'name="dht_message"', 'name="dht_website"', 'name="dht_consent"', 'name="dht_ts"', 'name="dht_sig"'] as $f) {
$check(str_contains($html, $f), "Formular enthält $f");
}
$check(!str_contains($html, 'dh_geheimer_schluessel_123') && !str_contains($html, 'support.example.de'), 'Weder API-Schlüssel noch Server-Adresse stehen im Formular');
$check(str_contains($html, 'href="/datenschutz"') && !str_contains($html, 'onclick') && !str_contains($html, '', 'dht_consent' => '1'])));
$sent = json_decode((string) ($seen[0]['args']['body'] ?? ''), true);
$check(!str_contains((string) ($sent['message'] ?? ''), '<'), 'HTML in der Nachricht wird entfernt');
$check($st && !empty($st['ok']), 'Mit Einwilligung klappt es');
reset_wp(['consent_text' => '']);
$seen = []; $GLOBALS['wp_http_handler'] = ok_handler($seen);
$html = render_form(['topics' => 'Rechnung:3,Technik:4', 'department' => '5']);
$check(str_contains($html, '