Skip to content

Commit ae8c615

Browse files
Merge pull request #26 from LinioIT/feat/DIS-735-improve-features-of-born-date-type
[DIS-735] feat: improve features of birth date type
2 parents 40792a3 + d3a483b commit ae8c615

File tree

9 files changed

+460
-2
lines changed

9 files changed

+460
-2
lines changed

.php-cs-fixer.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,4 @@
3737
])
3838
->setFinder($finder)
3939
->setUsingCache(true)
40-
->setRiskyAllowed(true);
40+
->setRiskyAllowed(true);

README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,34 @@ dynamic_form:
9191
### Options
9292
Field options are the same as symfony, refer to the documentation
9393
94+
#### Birthday Type
95+
96+
Supports `Symfony >= 4.4`.
97+
98+
In addition to the own options that the field brings by default ([see documentation](https://symfony.com/doc/current/reference/forms/types/birthday.html)), we added 3 new attributes to make its behavior more flexible.
99+
100+
##### minAgeAllowed and maxAgeAllowed:
101+
102+
These options work together and it is an improvement to the `years` option because it is too strict to only receive an array with the allowed years (and that in our case we should leave static in our Yaml file). With them we can determine (taking the current date) the minimum and maximum number of ages to generate the years that will be displayed in the form. These options only accept whole numbers greater than or equal to zero.
103+
104+
For example, if we want to have a field of type `birthday` but we only want children who have between **5** and **10** years of life to be registered, we would have something like the following:
105+
106+
```yaml
107+
dynamic_form:
108+
new_user:
109+
birthday:
110+
enabled: true
111+
type: birthday
112+
options:
113+
minAgeAllowed: 5
114+
maxAgeAllowed: 10
115+
```
116+
117+
The above would generate this array of `years` => `[2016, 2015, 2014, 2013, 2012, 2011]` taking into account `2021` as the current year.
118+
119+
##### Order:
120+
121+
This option is used together with `minAgeAllowed` and `maxAgeAllowed` and is for the cases where we want to show our drop-down list of years in one order or another. The accepted values are **`asc`** and **`desc`**, the latter by default.
94122

95123
### Transformers
96124

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,4 @@
3333
"@phpunit"
3434
]
3535
}
36-
}
36+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Linio\DynamicFormBundle\Exception;
6+
7+
class InvalidConfigurationException extends DynamicFormException
8+
{
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Linio\DynamicFormBundle\Exception;
6+
7+
class NumberFormatException extends DynamicFormException
8+
{
9+
}
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 Linio\DynamicFormBundle\Form\Extension;
6+
7+
use Symfony\Component\Form\AbstractTypeExtension;
8+
use Symfony\Component\Form\Extension\Core\Type\BirthdayType;
9+
use Symfony\Component\Form\FormInterface;
10+
use Symfony\Component\Form\FormView;
11+
use Symfony\Component\OptionsResolver\OptionsResolver;
12+
13+
class BirthdayTypeExtension extends AbstractTypeExtension
14+
{
15+
public function configureOptions(OptionsResolver $resolver): void
16+
{
17+
$resolver->setDefined(['order', 'minAgeAllowed', 'maxAgeAllowed']);
18+
}
19+
20+
public function buildView(FormView $view, FormInterface $form, array $options): void
21+
{
22+
$view->vars['order'] = $options['order'] ?? '';
23+
$view->vars['minAgeAllowed'] = $options['minAgeAllowed'] ?? '';
24+
$view->vars['maxAgeAllowed'] = $options['maxAgeAllowed'] ?? '';
25+
}
26+
27+
public static function getExtendedTypes(): iterable
28+
{
29+
return [BirthdayType::class];
30+
}
31+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Linio\DynamicFormBundle\FormlyMapper\FormlyField;
6+
7+
use Linio\DynamicFormBundle\Exception\InvalidConfigurationException;
8+
use Linio\DynamicFormBundle\Exception\NumberFormatException;
9+
use Linio\DynamicFormBundle\FormlyMapper\FormlyField;
10+
11+
class BirthdayField extends FormlyField
12+
{
13+
const ORDER_ASC = 'asc';
14+
const ORDER_DESC = 'desc';
15+
16+
/**
17+
* {@inheritdoc}
18+
*/
19+
protected function getFieldType()
20+
{
21+
return 'birthday';
22+
}
23+
24+
/**
25+
* {@inheritdoc}
26+
*/
27+
protected function buildFieldTypeConfiguration(): void
28+
{
29+
$options = $this->fieldConfiguration['options'];
30+
31+
$this->validateNumberFormatForSpecificRangeOfYearsArray($options);
32+
$this->validateMaxAgeAllowedIsLargerThanMinAgeAllowed($options);
33+
34+
$this->formlyFieldConfiguration['templateOptions']['type'] = $this->getFieldType();
35+
36+
$order = isset($options['order']) && (strtolower($options['order']) == (self::ORDER_ASC || self::ORDER_DESC))
37+
? $options['order']
38+
: self::ORDER_DESC;
39+
40+
unset($this->formlyFieldConfiguration['templateOptions']['order']);
41+
42+
if (!isset($options['minAgeAllowed']) || !isset($options['maxAgeAllowed'])
43+
|| !is_numeric($options['minAgeAllowed']) || !is_numeric($options['maxAgeAllowed'])
44+
|| $options['minAgeAllowed'] < 0 || $options['maxAgeAllowed'] < 0) {
45+
$this->removeAgeAllowedFromTemplateOptions();
46+
47+
return;
48+
}
49+
50+
$yearsRange = range(date('Y') - $options['minAgeAllowed'], date('Y') - $options['maxAgeAllowed']);
51+
52+
$this->formlyFieldConfiguration['templateOptions']['years'] = ($order == self::ORDER_ASC)
53+
? array_reverse($yearsRange)
54+
: $yearsRange;
55+
56+
$this->removeAgeAllowedFromTemplateOptions();
57+
}
58+
59+
private function removeAgeAllowedFromTemplateOptions(): void
60+
{
61+
unset($this->formlyFieldConfiguration['templateOptions']['minAgeAllowed']);
62+
unset($this->formlyFieldConfiguration['templateOptions']['maxAgeAllowed']);
63+
}
64+
65+
private function validateNumberFormatForSpecificRangeOfYearsArray(array $options): void
66+
{
67+
if (!isset($options['years'])) {
68+
return;
69+
}
70+
71+
foreach ($options['years'] as $key => $year) {
72+
if (!is_numeric($year)) {
73+
throw new NumberFormatException(sprintf('The year "%s" does not have a valid number format.', $year));
74+
}
75+
76+
$options['years'][$key] = (int) $year;
77+
}
78+
}
79+
80+
private function validateMaxAgeAllowedIsLargerThanMinAgeAllowed(array $options): void
81+
{
82+
if (!isset($options['minAgeAllowed']) || !isset($options['maxAgeAllowed'])) {
83+
return;
84+
}
85+
86+
if ($options['minAgeAllowed'] > $options['maxAgeAllowed']) {
87+
throw new InvalidConfigurationException(sprintf('The value of minAgeAllowed (%s) cannot be greater than maxAgeAllowed (%s).', $options['minAgeAllowed'], $options['maxAgeAllowed']));
88+
}
89+
}
90+
}

src/Resources/config/services.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ services:
1515
container.formly_field:
1616
class: Linio\DynamicFormBundle\FormlyMapper\FormlyField\FormlyFieldFactory
1717

18+
formly_field.birthday:
19+
class: Linio\DynamicFormBundle\FormlyMapper\FormlyField\BirthdayField
20+
lazy: true
21+
tags:
22+
- {name: formly_field, alias: birthday}
23+
1824
formly_field.choice:
1925
class: Linio\DynamicFormBundle\FormlyMapper\FormlyField\ChoiceField
2026
lazy: true
@@ -109,3 +115,8 @@ services:
109115
class: Linio\DynamicFormBundle\Form\Extension\HelpMessageTypeExtension
110116
tags:
111117
- {name: form.type_extension, extended_type: Symfony\Component\Form\Extension\Core\Type\FormType}
118+
119+
form.type_extension.birthday:
120+
class: Linio\DynamicFormBundle\Form\Extension\BirthdayTypeExtension
121+
tags:
122+
- {name: form.type_extension, extended_type: Symfony\Component\Form\Extension\Core\Type\BirthdayType}

0 commit comments

Comments
 (0)