201 lines
5.7 KiB
PHP
201 lines
5.7 KiB
PHP
<?php
|
||
|
||
/**
|
||
* При рендеринге каждому классу соответствует шаблон (см. themes/maxim/templates/macros.html)
|
||
*/
|
||
|
||
namespace ctiso\Form;
|
||
|
||
use ctiso\Form\Field;
|
||
use ctiso\Form\Select;
|
||
use ctiso\Form\Input;
|
||
use ctiso\Validator\Validator;
|
||
use ctiso\HttpRequest;
|
||
|
||
/**
|
||
* Форма для ввода
|
||
*/
|
||
class Form {
|
||
/** @var array */
|
||
public $field = []; //Поля формы
|
||
/** @var array */
|
||
public $fieldsets = []; //Группы полей (fieldset). Некоторые поля могут не принадлежать никаким группам
|
||
|
||
/** @var string */
|
||
public $action = "";
|
||
/** @var string */
|
||
public $method = 'post';
|
||
/** @var string */
|
||
public $header;
|
||
|
||
protected $replace;
|
||
protected $before;
|
||
|
||
/** @var array<string> */
|
||
public $_title = [];
|
||
/** @var array */
|
||
public $alias = [];
|
||
/** @var class-string<Field>[] */
|
||
private $constructor = [];
|
||
|
||
/**
|
||
* Строим форму по ее структуре. Каждому типу соответствует определенный класс.
|
||
*/
|
||
public function __construct()
|
||
{
|
||
$this->constructor = [
|
||
'input' => Input::class,
|
||
// input с проверкой на заполненность
|
||
'inputreq' => Input::class,
|
||
'date' => Date::class,
|
||
'datereq' => Date::class,
|
||
'datetime' => DateTime::class,
|
||
|
||
'color' => Color::class,
|
||
'textarea' => TextArea::class,
|
||
'text' => TextArea::class,
|
||
'multiselect' => SelectMany::class,
|
||
'select1' => SelectOne::class,
|
||
'select' => SelectOne::class,
|
||
|
||
'questiontype'=> QuestionType::class,
|
||
'secret' => Secret::class,
|
||
'upload' => Upload::class,
|
||
'image' => Upload::class,
|
||
'checkbox' => CheckBox::class,
|
||
'checkmany' => SelectMany::class,
|
||
'hidden' => Hidden::class,
|
||
'radio' => SelectOne::class,
|
||
'filebrowser' => BrowserInput::class,
|
||
'documents' => BrowserInput::class,
|
||
'chooser' => Input::class,
|
||
'select_chooser' => SelectOne::class,
|
||
'html_text' => HtmlText::class
|
||
];
|
||
|
||
}
|
||
|
||
function getId(): string
|
||
{
|
||
return '_form_edit';
|
||
}
|
||
|
||
/**
|
||
* Добавление конструкторя для поля формы
|
||
* @param string $name Краткое название поля
|
||
* @param class-string<Field> $class
|
||
*/
|
||
public function addFieldClass($name, $class): void
|
||
{
|
||
$this->constructor [$name] = $class;
|
||
}
|
||
|
||
/**
|
||
* Добавляет одно поле ввода на форму
|
||
* @param array{ type: string, name: string, hint?: string } $init
|
||
* @param OptionsFactory|null $factory
|
||
*/
|
||
public function addField(array $init, $factory = null): Field
|
||
{
|
||
assert(isset($init['type']));
|
||
assert(isset($init['name']));
|
||
|
||
$constructor = $this->constructor[$init['type']];
|
||
$el = new $constructor($init, $factory);
|
||
if (!$el->type) {
|
||
$el->type = $init['type'];
|
||
}
|
||
|
||
if(isset($init['hint'])) {
|
||
$el->hint = $init['hint'];
|
||
}
|
||
|
||
$this->field[$init['name']] = $el;
|
||
return $el;
|
||
}
|
||
|
||
/**
|
||
* Добавление fieldset на форму
|
||
*/
|
||
public function addFieldSet(array $fieldset): void
|
||
{
|
||
$this->fieldsets[$fieldset['name']] = $fieldset;
|
||
}
|
||
|
||
/**
|
||
* Добавление массива fieldset на форму
|
||
*/
|
||
public function addFieldSetList(array $list): void
|
||
{
|
||
foreach ($list as $fieldset) {
|
||
$this->addFieldSet($fieldset);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Добавляет список полей для формы
|
||
* @param array $list
|
||
*/
|
||
public function addFieldList(array $list, $factory = null): void
|
||
{
|
||
foreach ($list as $init) {
|
||
$this->addField($init, $factory);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Устанавливает ошибки после проверки
|
||
*/
|
||
function setError(Validator $validator): void
|
||
{
|
||
foreach ($validator->getErrorMsg() as $name => $error)
|
||
{
|
||
$this->field[$name]->error = true;
|
||
$this->field[$name]->error_msg = $error;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Устанавливает ошибку для поля
|
||
* @param string $name
|
||
* @param string $message
|
||
*/
|
||
function setFieldError($name, $message): void
|
||
{
|
||
$this->field[$name]->error = true;
|
||
$this->field[$name]->error_msg = $message;
|
||
}
|
||
|
||
/**
|
||
* Устанавливает значения из масива
|
||
*/
|
||
function setValues(HttpRequest $request): void {
|
||
foreach ($this->field as $key => $_) {
|
||
$value = $request->getRawData($this->method, $key);
|
||
$this->field[$key]->setValue($value);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Заполняет форму данными из обьекта
|
||
* @param object $data
|
||
* @param array $schema Связь между элементами формы и свойствами обьекта
|
||
*/
|
||
public function fill($data, array $schema): void
|
||
{
|
||
foreach ($schema as $key => $conv) {
|
||
list($value, $type) = $conv;
|
||
$this->field [$key]->setValue(call_user_func([\ctiso\Primitive::class, 'from_' . $type], $data->$value));
|
||
}
|
||
}
|
||
|
||
public function set($name, $value): void
|
||
{
|
||
$this->field[$name]->setValue($value);
|
||
}
|
||
|
||
function execute(): self
|
||
{
|
||
return $this;
|
||
}
|
||
}
|