1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Ffcms\Core\Helper\HTML\Form; |
4
|
|
|
|
5
|
|
|
|
6
|
|
|
use Ffcms\Core\App; |
7
|
|
|
use Ffcms\Core\Arch\Model; |
8
|
|
|
use Ffcms\Core\Exception\SyntaxException; |
9
|
|
|
use Ffcms\Core\Helper\HTML\System\NativeGenerator; |
10
|
|
|
use Ffcms\Core\Helper\Type\Arr; |
11
|
|
|
use Ffcms\Core\Helper\Type\Str; |
12
|
|
|
|
13
|
|
|
/** |
14
|
|
|
* Class FieldSelector. Form field builder instance. |
15
|
|
|
* @package Ffcms\Core\Helper\HTML\Form |
16
|
|
|
* @method text(string $name, ?array $properties = null, ?string $helper = null, ?string $layerFile = null) |
17
|
|
|
* @method password(string $name, ?array $properties = null, ?string $helper = null, ?string $layerFile = null) |
18
|
|
|
* @method hidden(string $name, ?array $properties = null) |
19
|
|
|
* @method select(string $name, ?array $properties = null, ?string $helper = null, ?string $layerFile = null) |
20
|
|
|
* @method checkbox(string $name, ?array $properties = null, ?string $helper = null, ?string $layerFile = null) |
21
|
|
|
* @method email(string $name, ?array $properties = null, ?string $helper = null, ?string $layerFile = null) |
22
|
|
|
* @method textarea(string $name, ?array $properties = null, ?string $helper = null, ?string $layerFile = null) |
23
|
|
|
* @method checkboxes(string $name, ?array $properties = null, ?string $helper = null, ?string $layerFile = null) |
24
|
|
|
* @method captcha(string $name, ?array $properties = null, ?string $helper = null, ?string $layerFile = null) |
25
|
|
|
* @method file(string $name, ?array $properties = null, ?string $helper = null, ?string $layerFile = null) |
26
|
|
|
* @method div(string $name, ?array $properties = null, ?string $helper = null, ?string $layerFile = null) |
27
|
|
|
* @method radio(string $name, ?array $properties = null, ?string $helper = null, ?string $layerFile = null) |
28
|
|
|
* @method multiselect(string $name, ?array $properties = null, ?string $helper = null, ?string $layerFile = null) |
29
|
|
|
*/ |
30
|
|
|
class FieldSelector extends NativeGenerator |
31
|
|
|
{ |
32
|
|
|
/** @var Model */ |
33
|
|
|
private $model; |
34
|
|
|
/** @var array */ |
35
|
|
|
private $layers; |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* FieldSelector constructor. |
39
|
|
|
* @param Model $model |
40
|
|
|
* @param array $defaultLayers |
41
|
|
|
*/ |
42
|
|
|
public function __construct(Model $model, array $defaultLayers = []) |
43
|
|
|
{ |
44
|
|
|
$this->model = $model; |
45
|
|
|
$this->layers = $defaultLayers; |
46
|
|
|
} |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* @param string $field |
50
|
|
|
* @param array|null $arguments |
51
|
|
|
* @return string|null |
52
|
|
|
*/ |
53
|
|
|
public function __call(string $field, ?array $arguments = null): ?string |
54
|
|
|
{ |
55
|
|
|
if ($arguments === null || count($arguments) < 1) |
56
|
|
|
return null; |
57
|
|
|
|
58
|
|
|
// get named arguments from passed array |
59
|
|
|
$name = (string)$arguments[0]; |
60
|
|
|
$rootName = $name; |
61
|
|
|
// set root element name if array dot-nested notation found |
62
|
|
|
if (Str::contains('.', $name)) |
63
|
|
|
$rootName = strstr($rootName, '.', true); |
64
|
|
|
// define properties, helper and layer |
65
|
|
|
$properties = null; |
66
|
|
|
$helper = null; |
67
|
|
|
$layer = null; |
68
|
|
|
if (isset($arguments[1])) |
69
|
|
|
$properties = (array)$arguments[1]; |
70
|
|
|
|
71
|
|
|
if (isset($arguments[2])) |
72
|
|
|
$helper = (string)$arguments[2]; |
73
|
|
|
|
74
|
|
|
if (isset($arguments[3])) |
75
|
|
|
$layer = (string)$arguments[3]; |
76
|
|
|
|
77
|
|
|
// check if model has attribute |
78
|
|
|
if (!property_exists($this->model, $rootName)) { |
79
|
|
|
if (App::$Debug) |
80
|
|
|
App::$Debug->addMessage('Field "' . $name . '" (' . $field . ') is not defined in model: [' . get_class($this->model) . ']', 'error'); |
81
|
|
|
|
82
|
|
|
return null; |
83
|
|
|
} |
84
|
|
|
|
85
|
|
|
// prepare default layer if not passed |
86
|
|
|
$layer = $this->findFieldLayer($field, $layer); |
87
|
|
|
// prepare html attributes, object value |
88
|
|
|
$attr = $this->model->getFormName() . '-' . $rootName; |
89
|
|
|
$label = $this->model->getLabel($name); |
90
|
|
|
$value = $this->model->{$rootName}; |
91
|
|
|
// check if dot-nested array used and update attr name |
92
|
|
|
if ($rootName !== $name) { |
93
|
|
|
$nesting = trim(strstr($name, '.'), '.'); |
94
|
|
|
$attr .= '-' . Str::replace('.', '-', $nesting); |
95
|
|
|
$value = Arr::getByPath($nesting, $value); |
96
|
|
|
} |
97
|
|
|
|
98
|
|
|
// initialize form fields constructor and build output dom html value |
99
|
|
|
$constructor = new Constructor($this->model, $this->model->getFormName(), $field); |
100
|
|
|
$elementDOM = $constructor->makeTag($name, $value, $properties); |
101
|
|
|
|
102
|
|
|
// if item is hidden - return tag without assign of global template |
103
|
|
|
if ($field === 'hidden') |
104
|
|
|
return $elementDOM; |
105
|
|
|
|
106
|
|
|
// prepare output html |
107
|
|
|
try { |
108
|
|
|
return App::$View->render($layer, [ |
109
|
|
|
'name' => $attr, |
110
|
|
|
'label' => $label, |
111
|
|
|
'item' => $elementDOM, |
112
|
|
|
'help' => self::nohtml($helper) |
113
|
|
|
]); |
114
|
|
|
} catch (SyntaxException $e) { |
115
|
|
|
if (App::$Debug) |
116
|
|
|
App::$Debug->addException($e); |
117
|
|
|
return null; |
118
|
|
|
} |
119
|
|
|
} |
120
|
|
|
|
121
|
|
|
/** |
122
|
|
|
* Find default layer if not passed direct |
123
|
|
|
* @param null|string $type |
124
|
|
|
* @param null|string $layer |
125
|
|
|
* @return null|string |
126
|
|
|
*/ |
127
|
|
|
private function findFieldLayer(?string $type = null, ?string $layer = null): ?string |
128
|
|
|
{ |
129
|
|
|
if ($layer !== null) |
130
|
|
|
return $layer; |
131
|
|
|
|
132
|
|
|
switch ($type) { |
133
|
|
|
case 'checkbox': |
|
|
|
|
134
|
|
|
$layer = $this->layers['checkbox']; |
135
|
|
|
break; |
136
|
|
|
case 'radio': |
|
|
|
|
137
|
|
|
$layer = $this->layers['radio']; |
138
|
|
|
break; |
139
|
|
|
default: |
|
|
|
|
140
|
|
|
$layer = $this->layers['base']; |
141
|
|
|
break; |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
return $layer; |
145
|
|
|
} |
146
|
|
|
} |
As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next
break
.There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.
To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.