-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFormBuilder.php
191 lines (176 loc) · 6.66 KB
/
FormBuilder.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
<?php
/**
* Qubus\Form
*
* @link https://github.com/QubusPHP/form
* @copyright 2023 Joshua Parker <[email protected]>
* @license https://opensource.org/licenses/mit-license.php MIT License
*
* @since 1.0.0
*/
declare(strict_types=1);
namespace Qubus\Form;
use Qubus\Exception\Data\TypeException;
use Qubus\Form\FormBuilder\Button;
use Qubus\Form\FormBuilder\ChoiceList;
use Qubus\Form\FormBuilder\Control;
use Qubus\Form\FormBuilder\Decorator;
use Qubus\Form\FormBuilder\Decorator\Dindent;
use Qubus\Form\FormBuilder\Decorator\SimpleFilter;
use Qubus\Form\FormBuilder\Decorator\SimpleValidation;
use Qubus\Form\FormBuilder\Decorator\Tidy;
use Qubus\Form\FormBuilder\Div;
use Qubus\Form\FormBuilder\Element;
use Qubus\Form\FormBuilder\Fieldset;
use Qubus\Form\FormBuilder\Group;
use Qubus\Form\FormBuilder\Hyperlink;
use Qubus\Form\FormBuilder\Input;
use Qubus\Form\FormBuilder\Label;
use Qubus\Form\FormBuilder\Legend;
use Qubus\Form\FormBuilder\Select;
use Qubus\Form\FormBuilder\Span;
use Qubus\Form\FormBuilder\Textarea;
use ReflectionClass;
use ReflectionException;
use function array_slice;
use function func_get_args;
use function sprintf;
use const UPLOAD_ERR_CANT_WRITE;
use const UPLOAD_ERR_EXTENSION;
use const UPLOAD_ERR_FORM_SIZE;
use const UPLOAD_ERR_INI_SIZE;
use const UPLOAD_ERR_NO_FILE;
use const UPLOAD_ERR_NO_TMP_DIR;
use const UPLOAD_ERR_PARTIAL;
/**
* FormBuilder factory
*/
class FormBuilder
{
/**
* Default options.
*
* @var array
*/
public static array $options = [
'render' => true, // Render element
'validate' => true, // Server-side validation
'validation-script' => true, // Include <script> for validation that isn't supported by HTML5
'add-hidden' => true, // Add hidden input for checkbox inputs
'required-suffix' => ' *', // Suffix label for required controls
'container' => 'div', // Place each form element in a container
'label' => true, // Add a label for each form element
'error:required' => "Please fill out this field",
'error:type' => "Please enter a {{type}}",
'error:min' => "Value must be greater or equal to {{min}}",
'error:max' => "Value must be less or equal to {{max}}",
'error:minlength' => "Please use {{minlength}} characters or more for this text",
'error:maxlength' => "Please shorten this text to {{maxlength}} characters or less",
'error:pattern' => "Please match the requested format",
'error:same' => "Please match the value of {{other}}",
'error:upload' => [
UPLOAD_ERR_INI_SIZE => "The uploaded file exceeds the upload_max_filesize directive in php.ini.",
UPLOAD_ERR_FORM_SIZE
=> "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.",
UPLOAD_ERR_PARTIAL => "The uploaded file was only partially uploaded.",
UPLOAD_ERR_NO_FILE => "No file was uploaded.",
UPLOAD_ERR_NO_TMP_DIR => "Missing a temporary folder.",
UPLOAD_ERR_CANT_WRITE => "Failed to write file to disk.",
UPLOAD_ERR_EXTENSION => "A PHP extension stopped the file upload.",
],
];
/**
* Element types.
*
* @var array
*/
public static array $elements = [
'div' => [Div::class, ['tagname' => 'div']],
'form' => [Form::class],
'fieldset' => [Fieldset::class],
'group' => [Group::class],
'span' => [Span::class],
'label' => [Label::class],
'legend' => [Legend::class],
'button' => [Button::class],
'link' => [Hyperlink::class],
'choice' => [ChoiceList::class],
'multi' => [ChoiceList::class, ['multiple' => true]],
'input' => [Input::class],
'select' => [Select::class],
'textarea' => [Textarea::class],
'boolean' => [Input::class, ['type' => 'checkbox']],
'text' => [Input::class, ['type' => 'text']],
'hidden' => [Input::class, ['type' => 'hidden']],
'file' => [Input::class, ['type' => 'file']],
'color' => [Input::class, ['type' => 'color']],
'number' => [Input::class, ['type' => 'number']],
'decimal' => [Input::class, ['type' => 'text'], ['pattern' => '-?\d+(\.\d+)?']],
'range' => [Input::class, ['type' => 'range']],
'date' => [Input::class, ['type' => 'date']],
'datetime' => [Input::class, ['type' => 'datetime-local']],
'time' => [Input::class, ['type' => 'time']],
'month' => [Input::class, ['type' => 'month']],
'week' => [Input::class, ['type' => 'week']],
'url' => [Input::class, ['type' => 'url']],
'email' => [Input::class, ['type' => 'email']],
];
/**
* Decorator types.
*
* @var array
*/
public static array $decorators = [
'filter' => SimpleFilter::class,
'validation' => SimpleValidation::class,
'tidy' => Tidy::class,
'indent' => Dindent::class,
];
/**
* Create a form element.
*
* @param string $type Element type
* @param array $options Element options
* @param array $attr HTML attributes
* @return Element|Control
* @throws TypeException
*/
public static function element(string $type, array $options = [], array $attr = []): Element|Control
{
if (! isset(static::$elements[$type])) {
throw new TypeException(
sprintf(
'Unknown element type `%s`.',
$type
)
);
}
$class = static::$elements[$type][0];
if (isset(static::$elements[$type][1])) {
$options += static::$elements[$type][1];
}
if (isset(static::$elements[$type][2])) {
$attr += static::$elements[$type][2];
}
return new $class($options, $attr);
}
/**
* Create a form decorator.
*
* @param string $type Decorator type
* @param mixed $_ Additional arguments are passed to the constructor.
* @return Decorator
* @throws TypeException
* @throws ReflectionException
*/
public static function decorator($type): Decorator
{
if (! isset(static::$decorators[$type])) {
throw new TypeException(sprintf('Unknown decorator `%s`.', $type));
}
$class = static::$decorators[$type];
$args = array_slice(func_get_args(), 1);
$refl = new ReflectionClass($class);
return $refl->newInstanceArgs($args);
}
}