88 lines
3.3 KiB
PHP
88 lines
3.3 KiB
PHP
<?php
|
|
|
|
use Reservair\Logger\Logger;
|
|
|
|
class RsvFormReservationElementHandler implements RsvFormElementHandler {
|
|
|
|
private function end_from_start(DateTime $start, int $block_size_minutes): DateTime {
|
|
return ($start)->modify("+{$block_size_minutes} minutes");
|
|
}
|
|
|
|
public function draw(RsvFormElementDefinition $element): void {
|
|
$timetable_id = (int) $element->getAttr('timetable_id');
|
|
$price_per_block = (float) $element->getAttr('price_per_block', 0);
|
|
$name = $element->getName();
|
|
?>
|
|
<div class="rsv-form-input-group">
|
|
<label class="rsv-form-label"><?= esc_html($element->getLabel()) ?></label>
|
|
<rsv-reservation-selector
|
|
timetable-id="<?= $timetable_id ?>"
|
|
name="<?= esc_attr($name) ?>"
|
|
price-per-block="<?= $price_per_block ?>"
|
|
class="rsv-form-field"
|
|
></rsv-reservation-selector>
|
|
</div>
|
|
<?php
|
|
}
|
|
|
|
/** Validate the payload and create the reservation. */
|
|
public function submit(RsvFormElementDefinition $def, int $submit_id, array $data, RsvFormSubmitResult $result): bool {
|
|
$name = $def->getName();
|
|
$payload = $data[$name] ?? null;
|
|
|
|
if ($def->isRequired() && is_null($payload)) {
|
|
$result->addError($name, 'required', 'Reservation payload is required');
|
|
return false;
|
|
}
|
|
|
|
if (!is_array($payload) || !array_key_exists('timetable_reservations', $payload)) {
|
|
$result->addError($name, 'invalid', 'Reservation payload must be an object with timetable_reservations');
|
|
return false;
|
|
}
|
|
|
|
$timetable_id = intval($payload['timetable_id'] ?? null);
|
|
$timetable = (new RsvTimetableService())->get($timetable_id);
|
|
|
|
if (!$timetable) {
|
|
$result->addError($name, 'invalid', 'Invalid timetable ID');
|
|
return false;
|
|
}
|
|
|
|
$reservation = new RsvReservation(
|
|
0,
|
|
$submit_id,
|
|
false,
|
|
array_map(fn($t) => new RsvTimetableReservation(
|
|
0,
|
|
$timetable_id,
|
|
new DateTime($t),
|
|
$this->end_from_start(new DateTime($t), $timetable->block_size)
|
|
), $payload['timetable_reservations'])
|
|
);
|
|
|
|
try {
|
|
$reservation_id = (new RsvReservationService())->create($reservation);
|
|
} catch (\Throwable $e) {
|
|
// The slot may have been taken since the user selected it.
|
|
Logger::error($e);
|
|
$result->addError($name, 'creation_failed', 'Could not create the reservation. The slot may no longer be available.');
|
|
return false;
|
|
}
|
|
|
|
$result->setValue($name . '_reservation_id', $reservation_id);
|
|
|
|
$price_per_block = (float) $def->getAttr('price_per_block', 0);
|
|
$result->setValue($name . '_price', $price_per_block * count($payload['timetable_reservations']));
|
|
|
|
return true;
|
|
}
|
|
|
|
/** Delete the reservation created by submit(). */
|
|
public function rollback(RsvFormElementDefinition $def, int $submit_id, array $data, RsvFormSubmitResult $result): void {
|
|
$reservation_id = $result->getValue($def->getName() . '_reservation_id');
|
|
if ($reservation_id) {
|
|
(new RsvReservationService())->delete((int) $reservation_id);
|
|
}
|
|
}
|
|
}
|