Files
michaelschiemer/src/Framework/View/Components/FormSelect.php
Michael Schiemer fc3d7e6357 feat(Production): Complete production deployment infrastructure
- Add comprehensive health check system with multiple endpoints
- Add Prometheus metrics endpoint
- Add production logging configurations (5 strategies)
- Add complete deployment documentation suite:
  * QUICKSTART.md - 30-minute deployment guide
  * DEPLOYMENT_CHECKLIST.md - Printable verification checklist
  * DEPLOYMENT_WORKFLOW.md - Complete deployment lifecycle
  * PRODUCTION_DEPLOYMENT.md - Comprehensive technical reference
  * production-logging.md - Logging configuration guide
  * ANSIBLE_DEPLOYMENT.md - Infrastructure as Code automation
  * README.md - Navigation hub
  * DEPLOYMENT_SUMMARY.md - Executive summary
- Add deployment scripts and automation
- Add DEPLOYMENT_PLAN.md - Concrete plan for immediate deployment
- Update README with production-ready features

All production infrastructure is now complete and ready for deployment.
2025-10-25 19:18:37 +02:00

231 lines
6.7 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Framework\View\Components;
use App\Framework\View\ValueObjects\HtmlAttributes;
use App\Framework\View\ValueObjects\HtmlElement;
use App\Framework\View\ValueObjects\HtmlTag;
use App\Framework\View\ValueObjects\StandardHtmlElement;
use App\Framework\View\ValueObjects\TagName;
final readonly class FormSelect implements HtmlElement
{
public HtmlTag $tag;
public HtmlAttributes $attributes;
public string $content;
/**
* @param array<string, string> $options Key-value pairs for options
*/
public function __construct(
public string $name,
public array $options,
public ?string $selected = null,
public ?string $label = null,
public ?string $id = null,
public ?string $placeholder = null,
public bool $required = false,
public bool $disabled = false,
public bool $multiple = false,
public ?string $errorMessage = null,
public HtmlAttributes $additionalAttributes = new HtmlAttributes()
) {
$this->tag = new HtmlTag(TagName::DIV);
$this->attributes = HtmlAttributes::empty()->withClass('form-group');
$this->content = $this->buildContent();
}
public static function create(
string $name,
array $options,
?string $label = null
): self {
return new self(name: $name, options: $options, label: $label);
}
public function withSelected(string $selected): self
{
return new self(
name: $this->name,
options: $this->options,
selected: $selected,
label: $this->label,
id: $this->id,
placeholder: $this->placeholder,
required: $this->required,
disabled: $this->disabled,
multiple: $this->multiple,
errorMessage: $this->errorMessage,
additionalAttributes: $this->additionalAttributes
);
}
public function withRequired(bool $required = true): self
{
return new self(
name: $this->name,
options: $this->options,
selected: $this->selected,
label: $this->label,
id: $this->id,
placeholder: $this->placeholder,
required: $required,
disabled: $this->disabled,
multiple: $this->multiple,
errorMessage: $this->errorMessage,
additionalAttributes: $this->additionalAttributes
);
}
public function withMultiple(bool $multiple = true): self
{
return new self(
name: $this->name,
options: $this->options,
selected: $this->selected,
label: $this->label,
id: $this->id,
placeholder: $this->placeholder,
required: $this->required,
disabled: $this->disabled,
multiple: $multiple,
errorMessage: $this->errorMessage,
additionalAttributes: $this->additionalAttributes
);
}
public function withError(string $errorMessage): self
{
return new self(
name: $this->name,
options: $this->options,
selected: $this->selected,
label: $this->label,
id: $this->id,
placeholder: $this->placeholder,
required: $this->required,
disabled: $this->disabled,
multiple: $this->multiple,
errorMessage: $errorMessage,
additionalAttributes: $this->additionalAttributes
);
}
private function buildContent(): string
{
$selectId = $this->id ?? "select-{$this->name}";
$attributes = HtmlAttributes::empty()
->withName($this->name)
->withId($selectId)
->withClass('form-select');
if ($this->required) {
$attributes = $attributes->withRequired();
}
if ($this->disabled) {
$attributes = $attributes->withDisabled();
}
if ($this->multiple) {
$attributes = $attributes->with('multiple', 'multiple');
}
if ($this->errorMessage !== null) {
$attributes = $attributes
->withClass('form-select--error')
->with('aria-invalid', 'true')
->with('aria-describedby', "{$selectId}-error");
}
// Merge additional attributes
foreach ($this->additionalAttributes->attributes as $name => $value) {
$attributes = $attributes->with($name, $value);
}
// Build options
$optionElements = [];
if ($this->placeholder !== null) {
$optionElements[] = StandardHtmlElement::create(
TagName::OPTION,
HtmlAttributes::empty()
->withValue('')
->withDisabled()
->withSelected(),
$this->placeholder
);
}
foreach ($this->options as $value => $text) {
$optionAttrs = HtmlAttributes::empty()->withValue($value);
if ($this->selected !== null && $value === $this->selected) {
$optionAttrs = $optionAttrs->withSelected();
}
$optionElements[] = StandardHtmlElement::create(
TagName::OPTION,
$optionAttrs,
$text
);
}
$selectContent = implode('', array_map('strval', $optionElements));
$elements = [];
// Label
if ($this->label !== null) {
$labelAttrs = HtmlAttributes::empty()
->withClass('form-label')
->with('for', $selectId);
if ($this->required) {
$labelAttrs = $labelAttrs->withClass('form-label--required');
}
$elements[] = StandardHtmlElement::create(
TagName::LABEL,
$labelAttrs,
$this->label
);
}
// Select
$elements[] = StandardHtmlElement::create(
TagName::SELECT,
$attributes,
$selectContent
);
// Error message
if ($this->errorMessage !== null) {
$elements[] = StandardHtmlElement::create(
TagName::SPAN,
HtmlAttributes::empty()
->withClass('form-error')
->withId("{$selectId}-error")
->with('role', 'alert'),
$this->errorMessage
);
}
return implode('', array_map('strval', $elements));
}
public function __toString(): string
{
return (string) StandardHtmlElement::create(
$this->tag->name,
$this->attributes,
$this->content
);
}
}