@@ -180,11 +180,18 @@ class RsvEmailListener {
|
||||
global $rsv_template_registry;
|
||||
$engine = new RsvTemplateEngine(registry: $rsv_template_registry);
|
||||
|
||||
$form_definition = new RsvFormDefinition((string) $form_submit['form_id'], $definition['definition']);
|
||||
$form_data = new RsvFormData($form_values);
|
||||
|
||||
// Calculated values (e.g. price) win over submitted fields so they can't be shadowed.
|
||||
$symbols = array_merge($form_values, (new RsvFormCalculatedValues())->for($form_definition, $form_data));
|
||||
|
||||
// Subject is plain text: render without HTML-escaping, then strip tags/newlines.
|
||||
$subject = sanitize_text_field($engine->render_plain($subject_tpl, $form_values));
|
||||
$subject = sanitize_text_field($engine->render_plain($subject_tpl, $symbols));
|
||||
|
||||
// Body is HTML: the engine HTML-escapes all interpolated values.
|
||||
$body = $engine->render($body_tpl, $form_values);
|
||||
$body = $engine->render($body_tpl, $symbols);
|
||||
error_log("Prc");
|
||||
|
||||
(new RsvEmailSender())->send($user_email, $subject, $body);
|
||||
} catch (\Throwable $e) {
|
||||
|
||||
@@ -15,7 +15,7 @@ class RsvGoogleCalendarListener {
|
||||
return;
|
||||
}
|
||||
|
||||
$calendar_id = self::resolve_calendar_id($gcal, $event->timetable_id);
|
||||
$calendar_id = self::resolve_calendar_id($gcal, $event->reservation->timetable_id);
|
||||
if (!$calendar_id) {
|
||||
return;
|
||||
}
|
||||
@@ -24,8 +24,8 @@ class RsvGoogleCalendarListener {
|
||||
$gcal->add_event(
|
||||
$calendar_id,
|
||||
"Reservation #{$event->reservation->id}",
|
||||
$event->reservation->start,
|
||||
$event->reservation->end,
|
||||
$event->reservation->start_utc,
|
||||
$event->reservation->end_utc,
|
||||
$event->reservation->user_email,
|
||||
$event->reservation->id,
|
||||
$status,
|
||||
|
||||
@@ -50,6 +50,7 @@ class RsvTimetableRepository {
|
||||
'name' => $timetable->name,
|
||||
'block_size' => $timetable->block_size,
|
||||
'maintainer_email' => $timetable->maintainer_email,
|
||||
'google_calendar_id' => $timetable->google_calendar_id,
|
||||
],
|
||||
['id' => $id]
|
||||
);
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/** Computes a form's total price as the sum of its elements' prices. */
|
||||
class RsvFormPriceCalculator {
|
||||
public function calculate(RsvFormDefinition $definition, RsvFormData $data): float {
|
||||
global $rsv_form_price_registry;
|
||||
|
||||
$total = 0.0;
|
||||
|
||||
foreach ($definition->getElements() as $element) {
|
||||
$calculator = $rsv_form_price_registry->get($element->getType());
|
||||
if ($calculator === null) {
|
||||
continue; // Unpriced element type contributes nothing.
|
||||
}
|
||||
|
||||
$total += (float) $calculator($element, $data->getValue($element->getName()));
|
||||
}
|
||||
|
||||
return $total;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
class RsvFormPriceCalculatorRegistry {
|
||||
/** @var array<string, callable(RsvFormElementDefinition, mixed): float> */
|
||||
private array $calculators = [];
|
||||
|
||||
public function register(string $type, callable $calculator): void {
|
||||
$this->calculators[$type] = $calculator;
|
||||
}
|
||||
|
||||
public function get(string $type): ?callable {
|
||||
return $this->calculators[$type] ?? null;
|
||||
}
|
||||
|
||||
/** Builds the registry and lets other modules contribute calculators. */
|
||||
public static function boot(): self {
|
||||
$registry = new self();
|
||||
do_action('rsv-register-price-calculator', $registry);
|
||||
return $registry;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
/** Values derived from a submission (not entered by the visitor), exposed to templates. */
|
||||
final class RsvFormCalculatedValues {
|
||||
/** @return array<string, mixed> */
|
||||
public function for(RsvFormDefinition $definition, RsvFormData $data): array {
|
||||
return [
|
||||
'price' => (new RsvFormPriceCalculator())->calculate($definition, $data),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* The names these values expose, so template validation accepts {{ price }}.
|
||||
* @return list<string>
|
||||
*/
|
||||
public static function names(): array {
|
||||
return ['price'];
|
||||
}
|
||||
}
|
||||
@@ -44,7 +44,7 @@ final class RsvFormDefinitionValidator {
|
||||
* @return list<string>
|
||||
*/
|
||||
private function symbols(array $elements): array {
|
||||
$names = [];
|
||||
$names = RsvFormCalculatedValues::names(); // calculated values are referencable too
|
||||
foreach ($elements as $el) {
|
||||
$name = is_array($el) ? ($el['name'] ?? '') : '';
|
||||
if (is_string($name) && $name !== '') {
|
||||
|
||||
Reference in New Issue
Block a user