Form

mail@pastecode.io avatar
unknown
php
a year ago
3.4 kB
7
Indexable
<?php

class Input
{
    public function __construct(
        private readonly string $type,
        private readonly string $name,
        private readonly string $defaultValue = '',
        private readonly array $parameters = [],
    ) {
    }

    public function render(): string
    {
        $attributes = [
            'type' => $this->type,
            'name' => $this->name,
            'id' => $this->name,
            'value' => $this->defaultValue,
            ...$this->parameters,
        ];
        return sprintf('<input %s>', $this->renderHtmlAttributes($attributes));
    }

    protected function renderHtmlAttributes(array $attributes): string
    {
        $htmlAttributes = [];
        foreach ($attributes as $key => $value) {
            $htmlAttributes[] = sprintf('%s="%s"', $key, $value);
        }
        return implode(' ', $htmlAttributes);
    }
}

class InputSelect extends Input
{
    public function __construct(
        private readonly string $name,
        private readonly array $options,
        private readonly string $defaultValue = '',
        private readonly array $parameters = [],
    ) {
        parent::__construct('select', $name, $defaultValue, $parameters);
    }

    public function render(): string
    {
        $options = [];
        foreach ($this->options as $value => $label) {
            $selected = $value === $this->defaultValue ? 'selected' : '';
            $options[] = sprintf('<option value="%s" %s>%s</option>', $value, $selected, $label);
        }
        $options = implode('', $options);

        $attributes = [
            'name' => $this->name,
            'id' => $this->name,
            ...$this->parameters,
        ];

        return sprintf('<select %s>%s</select>', $this->renderHtmlAttributes($attributes), $options);
    }
}

class Label
{
    public function __construct(
        private readonly string $label,
        private readonly string $for,
        private readonly Input $input,
        private readonly string $position = 'before',
    ) {
    }

    public function render(): string
    {
        if ($this->position === 'before') {
            $label = sprintf('<label for="%s">%s</label>', $this->for, $this->label);
            return $label . $this->input->render();
        }

        if ($this->position === 'after') {
            $label = sprintf('<label for="%s">%s</label>', $this->for, $this->label);
            return $this->input->render() . $label;
        }

        // Input inner label
        $inputRender = $this->input->render();
        return "<label for='{$this->for}'>{$this->label}{$inputRender}</label>";
    }
}

class FormBuilder
{
    public static function createInput(string $type, string $name, string $defaultValue = '', array $parameters = []): Input
    {
        return new Input($type, $name, $defaultValue, $parameters);
    }
    
    public static function createInputSelect(string $name, array $options, string $defaultValue = '', array $parameters = []): InputSelect
    {
        return new InputSelect($name, $options, $defaultValue, $parameters);
    }
    
    public static function createLabel(string $label, string $for, Input $input, string $position = 'before'): Label
    {
        return new Label($label, $for, $input, $position);
    }
}

echo FormBuilder::createLabel('Name', 'name', FormBuilder::createInput('text', 'name'))->render();