1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Ffcms\Core\Helper\HTML\Form; |
4
|
|
|
|
5
|
|
|
use Ffcms\Core\App; |
6
|
|
|
use Ffcms\Core\Arch\Model; |
7
|
|
|
use Ffcms\Core\Exception\SyntaxException; |
8
|
|
|
use Ffcms\Core\Helper\Type\Any; |
9
|
|
|
use Ffcms\Core\Helper\Type\Obj; |
10
|
|
|
use Ffcms\Core\Helper\Type\Str; |
11
|
|
|
|
12
|
|
|
/** |
13
|
|
|
* Class Constructor. Form field construction manager. |
14
|
|
|
* @package Ffcms\Core\Helper\HTML\Form |
15
|
|
|
*/ |
16
|
|
|
class Constructor |
17
|
|
|
{ |
18
|
|
|
const TYPE_TEXT = 'text'; |
19
|
|
|
const TYPE_PASSWORD = 'password'; |
20
|
|
|
const TYPE_EMAIL = 'email'; |
21
|
|
|
const TYPE_CHECKBOX = 'checkbox'; |
22
|
|
|
const TYPE_SELECT = 'select'; |
23
|
|
|
const TYPE_MULTISELECT = 'multiselect'; |
24
|
|
|
const TYPE_TEXTAREA = 'textarea'; |
25
|
|
|
const TYPE_MULTI_CHECKBOXES = 'checkboxes'; |
26
|
|
|
const TYPE_CAPTCHA = 'captcha'; |
27
|
|
|
const TYPE_FILE = 'file'; |
28
|
|
|
const TYPE_HIDDEN = 'hidden'; |
29
|
|
|
const TYPE_DIV_FAKE = 'div'; |
30
|
|
|
const TYPE_RADIO = 'radio'; |
31
|
|
|
|
32
|
|
|
/** @var \Ffcms\Core\Arch\Model $model */ |
33
|
|
|
private $model; |
34
|
|
|
private $formName; |
35
|
|
|
private $type; |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* Initialize Constructor. Pass model and type inside of current field inside. |
39
|
|
|
* @param \Ffcms\Core\Arch\Model $model |
40
|
|
|
* @param string|null $formName |
41
|
|
|
* @param string $type |
42
|
|
|
*/ |
43
|
|
|
public function __construct(Model $model, ?string $formName = null, ?string $type = 'text') |
44
|
|
|
{ |
45
|
|
|
$this->model = $model; |
46
|
|
|
$this->formName = $formName; |
47
|
|
|
$this->type = $type; |
48
|
|
|
} |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* @param string|array $name |
52
|
|
|
* @param string|array|null $value |
53
|
|
|
* @param array|null $properties |
54
|
|
|
* @return null|string |
55
|
|
|
*/ |
56
|
|
|
public function makeTag($name, $value = null, ?array $properties = null): ?string |
57
|
|
|
{ |
58
|
|
|
// check if properties is passed well |
59
|
|
|
if ($properties !== null && !Any::isArray($properties)) |
60
|
|
|
return null; |
61
|
|
|
|
62
|
|
|
// add properties to autovalidation by js (properties passed by ref) |
63
|
|
|
$this->addValidationProperties($name, $properties); |
|
|
|
|
64
|
|
|
// set default form data as properties: name="", value="", id="" based tag info |
65
|
|
|
$this->setDefaultProperties($name, $value, $properties); |
|
|
|
|
66
|
|
|
|
67
|
|
|
// initialize build model depend of current type |
68
|
|
|
switch ($this->type) { |
69
|
|
|
case static::TYPE_TEXT: // for <input type="text"> |
|
|
|
|
70
|
|
|
$builder = new TextField($properties, $name); |
|
|
|
|
71
|
|
|
break; |
72
|
|
|
case static::TYPE_CHECKBOX: |
|
|
|
|
73
|
|
|
$builder = new CheckboxField($properties, $name, $value); |
|
|
|
|
74
|
|
|
break; |
75
|
|
|
case static::TYPE_PASSWORD: |
|
|
|
|
76
|
|
|
$builder = new PasswordField($properties, $name); |
|
|
|
|
77
|
|
|
break; |
78
|
|
|
case static::TYPE_EMAIL: |
79
|
|
|
$builder = new EmailField($properties, $name); |
|
|
|
|
80
|
|
|
break; |
81
|
|
|
case static::TYPE_SELECT: |
82
|
|
|
$builder = new SelectField($properties, $name, $value); |
|
|
|
|
83
|
|
|
break; |
84
|
|
|
case static::TYPE_TEXTAREA: |
85
|
|
|
$builder = new TextareaField($properties, $name, $value); |
|
|
|
|
86
|
|
|
break; |
87
|
|
|
case static::TYPE_MULTI_CHECKBOXES: |
88
|
|
|
$builder = new MultiCheckboxField($properties, $name, $value); |
|
|
|
|
89
|
|
|
break; |
90
|
|
|
case static::TYPE_CAPTCHA: |
91
|
|
|
$builder = new CaptchaField($properties, $name); |
|
|
|
|
92
|
|
|
break; |
93
|
|
|
case static::TYPE_FILE: |
94
|
|
|
$builder = new FileField($properties, $name); |
|
|
|
|
95
|
|
|
break; |
96
|
|
|
case static::TYPE_HIDDEN: |
97
|
|
|
$builder = new HiddenField($properties, $name, $value); |
|
|
|
|
98
|
|
|
break; |
99
|
|
|
case static::TYPE_DIV_FAKE: |
100
|
|
|
$builder = new DivFakeField($properties, $name, $value); |
|
|
|
|
101
|
|
|
break; |
102
|
|
|
case static::TYPE_MULTISELECT: |
103
|
|
|
$builder = new MultiSelectField($properties, $name, $value); |
|
|
|
|
104
|
|
|
break; |
105
|
|
|
case static::TYPE_RADIO: |
106
|
|
|
$builder = new RadioField($properties, $name, $value); |
|
|
|
|
107
|
|
|
break; |
108
|
|
|
default: |
109
|
|
|
if (App::$Debug) |
110
|
|
|
App::$Debug->addMessage('Field has unknown type: ' . App::$Security->strip_tags($name)); |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
return $builder->make(); |
|
|
|
|
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
/** |
117
|
|
|
* Set validator options to current properties |
118
|
|
|
* @param string $name |
119
|
|
|
* @param array|null $properties |
120
|
|
|
* @return void |
121
|
|
|
*/ |
122
|
|
|
private function addValidationProperties(string $name, ?array &$properties = null): void |
123
|
|
|
{ |
124
|
|
|
// jquery validation quick-build some rules |
125
|
|
|
$rules = $this->model->getValidationRule($name); |
126
|
|
|
if (count($rules) > 0) { |
127
|
|
|
foreach ($rules as $type => $value) { |
128
|
|
|
switch ($type) { |
129
|
|
|
case 'required': |
130
|
|
|
$properties['required'] = null; |
131
|
|
|
break; |
132
|
|
|
case 'length_min': |
133
|
|
|
$properties['minlength'] = $value; |
134
|
|
|
break; |
135
|
|
|
case 'length_max': |
136
|
|
|
$properties['maxlength'] = $value; |
137
|
|
|
break; |
138
|
|
|
} |
139
|
|
|
} |
140
|
|
|
} |
141
|
|
|
} |
142
|
|
|
|
143
|
|
|
/** |
144
|
|
|
* Prepare field global properties - name, id and value |
145
|
|
|
* @param string $name |
146
|
|
|
* @param string|null $value |
147
|
|
|
* @param array|null $properties |
148
|
|
|
*/ |
149
|
|
|
private function setDefaultProperties(string $name, $value = null, array &$properties = null): void |
150
|
|
|
{ |
151
|
|
|
// standard property data definition |
152
|
|
|
$properties['name'] = $properties['id'] = $this->formName; // form global name |
153
|
|
|
if ($value !== null && !Any::isEmpty($value)) |
154
|
|
|
$properties['value'] = $value; |
155
|
|
|
|
156
|
|
|
// sounds like a array-path based obj name |
157
|
|
|
if (Str::contains('.', $name)) { |
158
|
|
|
$splitedName = explode('.', $name); |
159
|
|
|
foreach ($splitedName as $nameKey) { |
160
|
|
|
$properties['name'] .= '[' . $nameKey . ']'; |
161
|
|
|
$properties['id'] .= '-' . $nameKey; |
162
|
|
|
} |
163
|
|
|
} else { // standard property definition - add field name |
164
|
|
|
$properties['name'] .= '[' . $name . ']'; |
165
|
|
|
$properties['id'] .= '-' . $name; |
166
|
|
|
} |
167
|
|
|
} |
168
|
|
|
} |
This check looks at variables that have been passed in as parameters and are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.