Skip to content

Commit c4d1342

Browse files
authored
add type, count, choice constraint, add format option to date fields (#380)
* add type, count, choice constraint, add format option to date fields
1 parent 7d52a57 commit c4d1342

File tree

13 files changed

+164
-21
lines changed

13 files changed

+164
-21
lines changed

UPGRADE.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Upgrade Notes
22

3+
## Version 4.4.0
4+
- **[ENHANCEMENT]**: Added `format` option to `Birthday`, `DateTime` and `DateField`
5+
- **[ENHANCEMENT]**: Translate all non-default constraints messages (Key contains `message`)
6+
- **[ENHANCEMENT]**: New Constraints added:
7+
- `Symfony\Component\Validator\Constraints\Type`
8+
- `Symfony\Component\Validator\Constraints\Count`
9+
- `Symfony\Component\Validator\Constraints\Choice`
10+
311
## Version 4.3.2
412
- **[BUGFIX]**: Assert valid timezone in date time fallback output transformer
513

src/FormBuilderBundle/Builder/FrontendFormBuilder.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,9 @@ public function buildForm(FormDefinitionInterface $formDefinition, array $formRu
101101
private function addFormAttributes(array $currentAttributes, array $attributes): array
102102
{
103103
foreach ($attributes as $attribute) {
104+
104105
// legacy
105-
if (!isset($attribute['option']) || is_null($attribute['option'])) {
106+
if (!isset($attribute['option'])) {
106107
continue;
107108
}
108109

src/FormBuilderBundle/Configuration/Configuration.php

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,24 +102,43 @@ public function getAvailableConstraints(): array
102102
continue;
103103
}
104104

105+
$constraintParameters = $refClass->getConstructor()?->getParameters();
105106
$defaultProperties = $refClass->getDefaultProperties();
106107
$constraintConfig = [];
108+
107109
foreach ($refClass->getProperties(\ReflectionProperty::IS_PUBLIC) as $refProperty) {
110+
108111
$propertyName = $refProperty->getName();
109112

110113
if (in_array($propertyName, $invalidProperties)) {
111114
continue;
112115
}
113116

114-
if (isset($defaultProperties[$propertyName])) {
117+
$constructorParameters = array_values(array_filter($constraintParameters ?? [], static function (\ReflectionParameter $parameter) use ($propertyName) {
118+
return $parameter->getName() === $propertyName;
119+
}));
120+
121+
$constructorParameterType = null;
122+
if (count($constructorParameters) > 0) {
123+
/** @var \ReflectionParameter $constructorParameter */
124+
$constructorParameter = $constructorParameters[0];
125+
if ($constructorParameter->hasType() && $constructorParameter->getType() instanceof \ReflectionNamedType) {
126+
$constructorParameterType = $constructorParameter->getType()->getName();
127+
}
128+
}
129+
130+
if ($constructorParameterType !== null) {
131+
$defaultValue = $defaultProperties[$propertyName] ?? null;
132+
$type = $constructorParameterType;
133+
} elseif (isset($defaultProperties[$propertyName])) {
115134
$defaultValue = $defaultProperties[$propertyName];
116135
$type = gettype($defaultValue);
117136
} else {
118137
$defaultValue = null;
119138
$type = 'string';
120139
}
121140

122-
if ($defaultValue === null || in_array(gettype($defaultValue), ['string', 'boolean', 'integer'])) {
141+
if ($defaultValue === null || in_array(gettype($defaultValue), ['string', 'boolean', 'bool', 'integer', 'int', 'array'])) {
123142
$constraintConfig[] = [
124143
'name' => $propertyName,
125144
'type' => $type,
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace FormBuilderBundle\Migrations;
6+
7+
use Doctrine\DBAL\Schema\Schema;
8+
use Doctrine\Migrations\AbstractMigration;
9+
use FormBuilderBundle\Tool\Install;
10+
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
11+
12+
final class Version20230303094642 extends AbstractMigration
13+
{
14+
use ContainerAwareTrait;
15+
16+
public function doesSqlMigrations(): bool
17+
{
18+
return false;
19+
}
20+
21+
public function up(Schema $schema): void
22+
{
23+
$installer = $this->container->get(Install::class);
24+
$installer->updateTranslations();
25+
}
26+
27+
public function down(Schema $schema): void
28+
{
29+
// nothing to do
30+
}
31+
}

src/FormBuilderBundle/Resources/config/backend/base_config.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,4 +134,16 @@ form_builder:
134134
time:
135135
class: Symfony\Component\Validator\Constraints\Time
136136
label: 'form_builder_validation_constraint.time'
137+
icon_class: form_builder_icon_validation
138+
type:
139+
class: Symfony\Component\Validator\Constraints\Type
140+
label: 'form_builder_validation_constraint.type'
141+
icon_class: form_builder_icon_validation
142+
count:
143+
class: Symfony\Component\Validator\Constraints\Count
144+
label: 'form_builder_validation_constraint.count'
145+
icon_class: form_builder_icon_validation
146+
choice:
147+
class: Symfony\Component\Validator\Constraints\Choice
148+
label: 'form_builder_validation_constraint.choice'
137149
icon_class: form_builder_icon_validation

src/FormBuilderBundle/Resources/config/types/type/birthday.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ form_builder:
2727
- ['Choice', 'choice']
2828
- ['Text', 'text']
2929
- ['Single Text', 'single_text']
30+
options.format:
31+
display_group_id: attributes
32+
type: textfield
33+
label: 'form_builder_type_field.date_format'
34+
config: ~
3035
options.days:
3136
display_group_id: attributes
3237
type: tagfield

src/FormBuilderBundle/Resources/config/types/type/date.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ form_builder:
2727
- ['Choice', 'choice']
2828
- ['Text', 'text']
2929
- ['Single Text', 'single_text']
30+
options.format:
31+
display_group_id: attributes
32+
type: textfield
33+
label: 'form_builder_type_field.date_format'
34+
config: ~
3035
options.days:
3136
display_group_id: attributes
3237
type: tagfield

src/FormBuilderBundle/Resources/config/types/type/date_time.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ form_builder:
3636
- ['Choice', 'choice']
3737
- ['Text', 'text']
3838
- ['Single Text', 'single_text']
39+
options.format:
40+
display_group_id: attributes
41+
type: textfield
42+
label: 'form_builder_type_field.format'
43+
config: ~
3944
options.seconds:
4045
display_group_id: attributes
4146
type: tagfield

src/FormBuilderBundle/Resources/install/translations/admin.csv

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@
3939
"form_builder_validation_constraint.iban","Iban","Iban"
4040
"form_builder_validation_constraint.date","Date","Datum"
4141
"form_builder_validation_constraint.date_time","Date & Time","Datum & Uhrzeit"
42+
"form_builder_validation_constraint.count","Count","Anzahl"
43+
"form_builder_validation_constraint.choice","Choice","Auswahl"
44+
"form_builder_validation_constraint.type","Type","Daten-Typ"
4245
"form_builder_validation_constraint.time","Time","Uhrzeit"
4346
"form_builder_container_type.fieldset","Fieldset","Fieldset"
4447
"form_builder_container_type.repeater","Repeater","Repeater"
@@ -104,6 +107,7 @@
104107
"form_builder_type_field.time_widget","Widget Time","Darstellung Uhrzeit"
105108
"form_builder_type_field.date_with_minutes","With Minutes","Minuten darstellen"
106109
"form_builder_type_field.date_with_seconds","With Seconds","Sekunden darstellen"
110+
"form_builder_type_field.date_format","Format","Format"
107111
"form_builder_type_field.recaptcha_v3.action_name","Action","Aktion"
108112
"form_builder_type_template.default","Default","Default"
109113
"form_builder_form_template.bootstrap_3_horizontal_layout","Bootstrap 3 Horizontal Layout","Bootstrap 3 Horizontales Layout"

src/FormBuilderBundle/Resources/public/js/extjs/components/formFieldConstraintComponent.js

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ Formbuilder.extjs.components.formFieldConstraint = Class.create({
155155

156156
break;
157157

158+
case 'bool':
158159
case 'boolean':
159160
field = new Ext.form.Checkbox({
160161
fieldLabel: configElement.name,
@@ -180,6 +181,7 @@ Formbuilder.extjs.components.formFieldConstraint = Class.create({
180181

181182
break;
182183

184+
case 'int':
183185
case 'integer':
184186
field = new Ext.form.field.Number({
185187
fieldLabel: configElement.name,
@@ -201,6 +203,57 @@ Formbuilder.extjs.components.formFieldConstraint = Class.create({
201203
}
202204
});
203205

206+
break;
207+
208+
case 'array':
209+
field = new Ext.form.field.Tag({
210+
fieldLabel: configElement.name,
211+
name: 'config.' + configElement.name,
212+
value: this.getFieldValue(configElement.name, configElement.defaultValue),
213+
flex: 2,
214+
queryDelay: 0,
215+
mode: 'local',
216+
displayField: 'name',
217+
valueField: 'index',
218+
store: new Ext.data.ArrayStore({
219+
fields: ['index', 'name'],
220+
data: []
221+
}),
222+
allowBlank: true,
223+
editable: true,
224+
hideTrigger: true,
225+
filterPickList: false,
226+
createNewOnBlur: true,
227+
createNewOnEnter: true,
228+
selectOnFocus: false,
229+
forceSelection: true,
230+
style: opacityStyle,
231+
getSubmitValue: function () {
232+
233+
if (Ext.isArray(this.getValue()) && this.getValue().length === 0) {
234+
return null;
235+
}
236+
237+
if (this.getValue() === configElement.defaultValue) {
238+
return null;
239+
}
240+
241+
return this.value;
242+
},
243+
listeners: {
244+
change: function (field, newVal, oldVal) {
245+
246+
if (Ext.isArray(this.getValue()) && this.getValue().length === 0) {
247+
newVal = null;
248+
}
249+
250+
console.warn(newVal, configElement.defaultValue);
251+
252+
field.setStyle('opacity', newVal !== configElement.defaultValue ? 1 : 0.6);
253+
}
254+
}
255+
});
256+
204257
break;
205258
}
206259

@@ -235,7 +288,7 @@ Formbuilder.extjs.components.formFieldConstraint = Class.create({
235288
}
236289

237290
var description = t('form_builder_constraint_default_value') + ': <code>' + defaultValue + '</code>';
238-
if (configElement.name === 'message') {
291+
if (Ext.isString(configElement.name) && configElement.name.toLowerCase().indexOf('message') !== -1) {
239292
description += '<br>' + t('form_builder_constraint_message_note');
240293
}
241294

0 commit comments

Comments
 (0)