1: <?php
2: namespace TIC\FormBundle\Form\Type;
3:
4: #use Symfony\Component\Form\AbstractType as BaseType;
5: use TIC\FormBundle\Base\TICWidgetType as BaseType;
6:
7: use Symfony\Component\OptionsResolver\OptionsResolver;
8: use Symfony\Component\OptionsResolver\Options;
9: use Symfony\Component\Form\FormBuilderInterface;
10: use Symfony\Component\Form\FormInterface;
11: use Symfony\Component\Form\FormView;
12:
13: #use Symfony\Component\Form\Extension\Core\DataTransformer\NumberToLocalizedStringTransformer as NumberTransformer;
14: use TIC\FormBundle\Form\DataTransformer\NumberToStringTransformer as NumberTransformer;
15:
16: /**
17: * Saisie d'une valeur numérique.
18: * Reprise du widget symfony avec options supplémentaires
19: * @TODO valeur par défaut du scale en fonction du step
20: */
21: class NumberType extends BaseType
22: {
23: # protected $form_parent = \Symfony\Component\Form\Extension\Core\Type\NumberType::class;
24:
25:
26: /**
27: * {@inheritdoc}
28: */
29: public function configureOptions(OptionsResolver $resolver): void
30: {
31: parent::configureOptions($resolver);
32:
33: $resolver->setDefaults(array(
34: 'compound' => false,
35: 'scale' => 0, // nombre entier par défaut (pas de détection auto selon la locale)
36: 'grouping' => false, // possibilité de passer le séparateur à utiliser
37: 'rounding_mode' => \NumberFormatter::ROUND_HALFUP,
38:
39: 'locale' => \Locale::getDefault(),
40: 'divisor' => null, // si besoin de diviser la valeur avant affichage
41: 'multiplier' => null, // si besoin de multiplier la valeur avant affichage
42: 'min' => null, // valeur minimale autorisée (attribut HTML5)
43: 'max' => null, // valeur maximale autorisée (attribut HTML5)
44: 'step' => null, // valeur pour l'incrément (attribut HTML5)
45: 'fixed' => false, // pour afficher les décimales nulles
46: 'mode' => 'text', // activation du mode 'html5' ou 'js'
47: ));
48:
49: $resolver->setAllowedTypes('scale', array('int'));
50: $resolver->setAllowedTypes('grouping', array('bool', 'string'));
51:
52: $resolver->setAllowedTypes('locale', array('string'));
53: $resolver->setAllowedTypes('divisor', array('null', 'int', 'float'));
54: $resolver->setAllowedTypes('multiplier', array('null', 'int', 'float'));
55: $resolver->setAllowedTypes('min', array('null', 'int', 'float', 'string'));
56: $resolver->setAllowedTypes('max', array('null', 'int', 'float', 'string'));
57: $resolver->setAllowedTypes('step', array('null', 'int', 'float'));
58: $resolver->setAllowedTypes('fixed', array('bool'));
59: $resolver->setAllowedTypes('mode', array('string'));
60:
61: $resolver->setAllowedValues('mode', array('text', 'html5', 'js'));
62: $resolver->setAllowedValues('rounding_mode', array(
63: \NumberFormatter::ROUND_FLOOR,
64: \NumberFormatter::ROUND_DOWN,
65: \NumberFormatter::ROUND_HALFDOWN,
66: \NumberFormatter::ROUND_HALFEVEN,
67: \NumberFormatter::ROUND_HALFUP,
68: \NumberFormatter::ROUND_UP,
69: \NumberFormatter::ROUND_CEILING,
70: ));
71: }
72:
73:
74: /**
75: * {@inheritdoc}
76: */
77: public function buildForm(FormBuilderInterface $builder, array $options): void
78: {
79: if ($options['multiplier'] === null && ! empty($options['divisor'])) $options['multiplier'] = 1 / $options['divisor'];
80:
81: // restrictions des fonctionnalités avec le mode html5
82: if ($options['mode'] === 'html5') {
83: if ($options['scale'] !== 0) {
84: @trigger_error("HTML5 input is not fully compatible with decimals (localization problems)");
85: # $options['scale'] = 0;
86: $options['locale'] = 'en';
87: }
88: if ($options['grouping'] !== false) {
89: @trigger_error("HTML5 input is not fully compatible with grouping");
90: $options['grouping'] = false;
91: }
92: };
93:
94: $builder->addViewTransformer(new NumberTransformer(
95: $options['scale'],
96: $options['grouping'],
97: $options['rounding_mode'],
98: $options['multiplier'],
99: $options['locale'],
100: $options['fixed']
101: ));
102: }
103:
104:
105: /**
106: * {@inheritdoc}
107: */
108: public function buildView(FormView $view, FormInterface $form, array $options): void
109: {
110: parent::buildView($view, $form, $options);
111:
112: // spécification de la taille du widget (ajout de classe bootstrap)
113: $this->setViewInputSizing($view);
114:
115: $view->vars['attr']['data-value'] = $form->getNormData();
116:
117: $attr_key = ($options['mode'] === 'html5') ? '' : 'data-';
118: if ($options['min'] !== null) $view->vars['attr'][$attr_key . 'min'] = $options['min'];
119: if ($options['max'] !== null) $view->vars['attr'][$attr_key . 'max'] = $options['max'];
120: if ($options['step']!== null) $view->vars['attr'][$attr_key . 'step']= $options['step'];
121:
122: if ($options['mode'] === 'html5') {
123: $view->vars['type'] = 'number';
124: $options['grouping'] = false;
125: }
126:
127: $transformers = $form->getConfig()->getViewTransformers();
128: foreach ($transformers as $transformer) {
129: if (! method_exists($transformer, 'getGroupingSep')) continue;
130: $view->vars['grouping_sep'] = $transformer->getGroupingSep();
131: $view->vars['decimal_sep'] = $transformer->getDecimalSep();
132: break;
133: }
134:
135: if ($options['grouping']) {
136: if (! isset($view->vars['attr']['class'])) $view->vars['attr']['class'] = '';
137: $view->vars['attr']['class'].= ' grouping';
138: $view->vars['attr']['data-grouping-sep'] = $view->vars['grouping_sep'];
139: }
140:
141: $view->vars['decimal_nb'] = ($options['fixed']) ? $options['scale'] : - $options['scale'];
142:
143: if (! empty($options['locale'])) {
144: $view->vars['attr']['lang'] = $view->vars['locale'] = $options['locale'];
145: }
146:
147: $view->vars['with_js'] = ($options['mode'] === 'js');
148: if ($view->vars['with_js']) {
149: if (! isset($view->vars['attr']['class'])) $view->vars['attr']['class'] = '';
150: $view->vars['attr']['class'].= ' tic-number-js';
151: }
152: }
153:
154:
155: }
156: