(#3) - templating

This commit was merged in pull request #9.
This commit is contained in:
Martin Slachta
2026-06-14 07:16:13 +02:00
parent f4d3972d07
commit 7d7f748f7a
31 changed files with 661 additions and 126 deletions
@@ -1,9 +0,0 @@
<?php
class RsvEmailTemplater {
public function render(string $template, array $data) : string {
return preg_replace_callback('/{{\s*(\w+)\s*}}/', function($matches) use ($data) {
return $data[$matches[1]] ?? '';
}, $template);
}
}
@@ -5,7 +5,7 @@ class RsvButtonElementHandler implements RsvFormElementHandler {
public function draw(RsvFormElementDefinition $element): void {
?>
<div class="rsv-form-input-group rsv-form-input-short">
<button class="rsv-form-btn-primary"><?= $element->getLabel() ?></button>
<button class="rsv-form-btn rsv-form-btn-primary"><?= $element->getLabel() ?></button>
</div>
<?php
}
@@ -1,6 +1,5 @@
<?php
interface RsvFormElementHandler {
function draw(RsvFormElementDefinition $def) : void;
@@ -14,7 +14,7 @@ class RsvFormReservationElementHandler implements RsvFormElementHandler {
$name = $element->getName();
?>
<div class="rsv-form-input-group">
<label><?= esc_html($element->getLabel()) ?></label>
<label class="rsv-form-label"><?= esc_html($element->getLabel()) ?></label>
<rsv-reservation-selector
timetable-id="<?= $timetable_id ?>"
name="<?= esc_attr($name) ?>"
+11 -3
View File
@@ -7,8 +7,10 @@ class RsvFormDefinition {
public string $email_key = "";
public string $success_message = "";
/**
* @param array<int,mixed> $definition Full definition array including 'elements' and 'email_key'.
* @param array<int,mixed> $definition Full definition array including 'elements', 'email_key' and 'success_message'.
*/
public function __construct(string $id, array $definition) {
$this->_elements = [];
@@ -19,8 +21,9 @@ class RsvFormDefinition {
}
}
$this->_id = $id;
$this->email_key = $definition['email_key'] ?? '';
$this->_id = $id;
$this->email_key = $definition['email_key'] ?? '';
$this->success_message = $definition['success_message'] ?? '';
}
public function getId(): string {
@@ -31,6 +34,11 @@ class RsvFormDefinition {
return $this->email_key;
}
/** Template shown to the visitor after a successful submission. */
public function getSuccessMessage(): string {
return $this->success_message;
}
public function hasElements() : bool {
return count($this->_elements) > 0;
@@ -1,5 +1,6 @@
<?php
use Reservair\Templating\RsvTemplateEngine;
class RsvFormHtmlRenderer {
public function draw(RsvFormDefinition $form): bool {
@@ -20,12 +21,37 @@ class RsvFormHtmlRenderer {
<?php endforeach; ?>
</form>
<?php $this->draw_success_template($form); ?>
</div>
<?php
return true;
}
/**
* Emits the admin-configured success message as an inert <template> that the
* client clones once the form is submitted. A <reservation-summary> element
* expands to a placeholder div that RsvFormSender fills with the visitor's
* selected slots.
*/
private function draw_success_template(RsvFormDefinition $form): void {
$message = trim($form->getSuccessMessage());
if ($message === '') {
return;
}
global $rsv_template_registry;
$engine = new RsvTemplateEngine(registry: $rsv_template_registry);
// Sanitize admin HTML before rendering, allowing the registered template
// custom elements through so the engine can expand them.
$allowed = $rsv_template_registry->kses_allowed(wp_kses_allowed_html('post'));
$html = $engine->render(wp_kses($message, $allowed));
?>
<template class="rsv-form-success"><?= $html ?></template>
<?php
}
public function draw_element(RsvFormElementDefinition $data): void {
global $rsv_form_registry;
@@ -35,6 +35,7 @@ class RsvTimetableReservationService {
->get_overlapping_capacity($timetable_id, $start_utc, $end_utc);
if (count($overlapping_capacity) === 0) {
Logger::error("No available capacity for timetable_id: $timetable_id, start_utc: " . $start_utc->format('Y-m-d H:i:s') . ", end_utc: " . $end_utc->format('Y-m-d H:i:s'));
return false;
}
@@ -42,6 +43,7 @@ class RsvTimetableReservationService {
$end_min = $this->time_of_day_minutes($end_utc);
if ((int) $overlapping_capacity[0]->start_time > $start_min) {
Logger::error("Overlapping capacity start_time: " . (int) $overlapping_capacity[0]->start_time . " is after the reservation start_time: $start_min");
return false;
}
@@ -59,6 +61,7 @@ class RsvTimetableReservationService {
$capacity = (int) $overlapping_capacity[0]->capacity;
$reservations = $this->repo->get_overlapping($timetable_id, $start_utc, $end_utc);
error_log('reservations: ' . json_encode($reservations));
return count($reservations) < $capacity;
}