Files
Reservair/modules/Forms/RsvFormGroup.php
T

188 lines
6.7 KiB
PHP
Raw Normal View History

2026-06-11 19:03:29 +02:00
<?php
namespace Reservair\Forms;
/**
* Inline field collector used inside RsvFormBuilder::group().
*
* Each method appends a labelled input fragment. On render() all fragments
* are placed in a flex row, emitted as the <td> content of a single table row.
*/
class RsvFormGroup
{
/** @var string[] */
private array $items = [];
private function __construct() {}
public static function create(): static
{
return new static();
}
// -------------------------------------------------------------------------
// Input methods
// -------------------------------------------------------------------------
public function text(
string $id,
string $label,
string $desc = '',
bool $required = false,
string $value = ''
): static {
$req = $required ? 'required' : '';
$ctrl = '<input class="regular-text" type="text" id="' . esc_attr($id) . '" name="' . esc_attr($id) . '" value="' . esc_attr($value) . '" ' . $req . '>';
return $this->item($id, $label, $ctrl, $desc);
}
public function email(
string $id,
string $label,
string $desc = '',
bool $required = false,
string $value = '',
?string $list_id = null
): static {
$req = $required ? 'required' : '';
$list = $list_id !== null ? 'list="' . esc_attr($list_id) . '"' : '';
$ctrl = '<input class="regular-text" type="email" id="' . esc_attr($id) . '" name="' . esc_attr($id) . '" value="' . esc_attr($value) . '" ' . $list . ' ' . $req . '>';
return $this->item($id, $label, $ctrl, $desc);
}
public function password(
string $id,
string $label,
string $desc = '',
bool $required = false,
string $placeholder = ''
): static {
$req = $required ? 'required' : '';
$ph = $placeholder !== '' ? 'placeholder="' . esc_attr($placeholder) . '"' : '';
$ctrl = '<input class="regular-text" type="password" id="' . esc_attr($id) . '" name="' . esc_attr($id) . '" ' . $ph . ' ' . $req . '>';
return $this->item($id, $label, $ctrl, $desc);
}
public function number(
string $id,
string $label,
string $desc = '',
bool $required = false,
string|int $value = '',
?int $min = null,
?int $max = null
): static {
$req = $required ? 'required' : '';
$min_attr = $min !== null ? 'min="' . $min . '"' : '';
$max_attr = $max !== null ? 'max="' . $max . '"' : '';
$ctrl = '<input class="small-text" type="number" id="' . esc_attr($id) . '" name="' . esc_attr($id) . '" value="' . esc_attr((string) $value) . '" ' . $min_attr . ' ' . $max_attr . ' ' . $req . '>';
return $this->item($id, $label, $ctrl, $desc);
}
public function date(
string $id,
string $label,
string $desc = '',
bool $required = false,
string $value = ''
): static {
$req = $required ? 'required' : '';
$ctrl = '<input class="regular-text" type="date" id="' . esc_attr($id) . '" name="' . esc_attr($id) . '" value="' . esc_attr($value) . '" ' . $req . '>';
return $this->item($id, $label, $ctrl, $desc);
}
public function time(
string $id,
string $label,
string $desc = '',
bool $required = false,
string $value = ''
): static {
$req = $required ? 'required' : '';
$ctrl = '<input type="time" id="' . esc_attr($id) . '" name="' . esc_attr($id) . '" value="' . esc_attr($value) . '" ' . $req . '>';
return $this->item($id, $label, $ctrl, $desc);
}
public function checkbox(
string $id,
string $label,
string $desc = '',
bool $checked = false
): static {
$c = $checked ? 'checked' : '';
$ctrl = '<input type="checkbox" id="' . esc_attr($id) . '" name="' . esc_attr($id) . '" ' . $c . '>';
return $this->item($id, $label, $ctrl, $desc);
}
/**
* @param array<string|int, string> $options Associative: value => display text.
*/
public function select(
string $id,
string $label,
array $options,
string $desc = '',
bool $required = false,
string $selected = ''
): static {
$req = $required ? 'required' : '';
$opts = $this->build_options($options, $selected);
$ctrl = '<select id="' . esc_attr($id) . '" name="' . esc_attr($id) . '" ' . $req . '>' . $opts . '</select>';
return $this->item($id, $label, $ctrl, $desc);
}
public function textarea(
string $id,
string $label,
string $desc = '',
bool $required = false,
string $value = '',
int $rows = 5
): static {
$req = $required ? 'required' : '';
$ctrl = '<textarea class="large-text" id="' . esc_attr($id) . '" name="' . esc_attr($id) . '" rows="' . $rows . '" ' . $req . '>'
. esc_textarea($value)
. '</textarea>';
return $this->item($id, $label, $ctrl, $desc);
}
// -------------------------------------------------------------------------
// Rendering
// -------------------------------------------------------------------------
public function render(): string
{
return '<div style="display:flex; gap:1.5em; align-items:flex-end; flex-wrap:wrap;">'
. implode('', $this->items)
. '</div>';
}
// -------------------------------------------------------------------------
// Private helpers
// -------------------------------------------------------------------------
private function item(string $id, string $label, string $control_html, string $desc): static
{
$d = $desc !== '' ? '<p class="description">' . esc_html($desc) . '</p>' : '';
$this->items[] = '<span style="display:flex; flex-direction:column; gap:.25em;">'
. '<label for="' . esc_attr($id) . '">' . esc_html($label) . '</label>'
. $control_html
. $d
. '</span>';
return $this;
}
/**
* @param array<string|int, string> $options
*/
private function build_options(array $options, string $selected): string
{
$html = '';
foreach ($options as $value => $text) {
$is_selected = (string) $value === $selected ? 'selected' : '';
$html .= '<option value="' . esc_attr((string) $value) . '" ' . $is_selected . '>' . esc_html($text) . '</option>';
}
return $html;
}
}