Upgraded drupal core with security updates
[yaffs-website] / web / core / modules / views / src / Plugin / views / field / NumericField.php
1 <?php
2
3 namespace Drupal\views\Plugin\views\field;
4
5 use Drupal\Core\Form\FormStateInterface;
6 use Drupal\Core\StringTranslation\PluralTranslatableMarkup;
7 use Drupal\views\ResultRow;
8
9 /**
10  * Render a field as a numeric value
11  *
12  * Definition terms:
13  * - float: If true this field contains a decimal value. If unset this field
14  *          will be assumed to be integer.
15  *
16  * @ingroup views_field_handlers
17  *
18  * @ViewsField("numeric")
19  */
20 class NumericField extends FieldPluginBase {
21
22   /**
23    * {@inheritdoc}
24    */
25   protected function defineOptions() {
26     $options = parent::defineOptions();
27
28     $options['set_precision'] = ['default' => FALSE];
29     $options['precision'] = ['default' => 0];
30     $options['decimal'] = ['default' => '.'];
31     $options['separator'] = ['default' => ','];
32     $options['format_plural'] = ['default' => FALSE];
33     $options['format_plural_string'] = ['default' => '1' . LOCALE_PLURAL_DELIMITER . '@count'];
34     $options['prefix'] = ['default' => ''];
35     $options['suffix'] = ['default' => ''];
36
37     return $options;
38   }
39
40   /**
41    * {@inheritdoc}
42    */
43   public function buildOptionsForm(&$form, FormStateInterface $form_state) {
44     if (!empty($this->definition['float'])) {
45       $form['set_precision'] = [
46         '#type' => 'checkbox',
47         '#title' => $this->t('Round'),
48         '#description' => $this->t('If checked, the number will be rounded.'),
49         '#default_value' => $this->options['set_precision'],
50       ];
51       $form['precision'] = [
52         '#type' => 'textfield',
53         '#title' => $this->t('Precision'),
54         '#default_value' => $this->options['precision'],
55         '#description' => $this->t('Specify how many digits to print after the decimal point.'),
56         '#states' => [
57           'visible' => [
58             ':input[name="options[set_precision]"]' => ['checked' => TRUE],
59           ],
60         ],
61         '#size' => 2,
62       ];
63       $form['decimal'] = [
64         '#type' => 'textfield',
65         '#title' => $this->t('Decimal point'),
66         '#default_value' => $this->options['decimal'],
67         '#description' => $this->t('What single character to use as a decimal point.'),
68         '#size' => 2,
69       ];
70     }
71     $form['separator'] = [
72       '#type' => 'select',
73       '#title' => $this->t('Thousands marker'),
74       '#options' => [
75         '' => $this->t('- None -'),
76         ',' => $this->t('Comma'),
77         ' ' => $this->t('Space'),
78         '.' => $this->t('Decimal'),
79         '\'' => $this->t('Apostrophe'),
80       ],
81       '#default_value' => $this->options['separator'],
82       '#description' => $this->t('What single character to use as the thousands separator.'),
83       '#size' => 2,
84     ];
85     $form['format_plural'] = [
86       '#type' => 'checkbox',
87       '#title' => $this->t('Format plural'),
88       '#description' => $this->t('If checked, special handling will be used for plurality.'),
89       '#default_value' => $this->options['format_plural'],
90     ];
91     $form['format_plural_string'] = [
92       '#type' => 'value',
93       '#default_value' => $this->options['format_plural_string'],
94     ];
95
96     $plural_array = explode(LOCALE_PLURAL_DELIMITER, $this->options['format_plural_string']);
97     $plurals = $this->getNumberOfPlurals($this->view->storage->get('langcode'));
98     for ($i = 0; $i < $plurals; $i++) {
99       $form['format_plural_values'][$i] = [
100         '#type' => 'textfield',
101         // @todo Should use better labels https://www.drupal.org/node/2499639
102         '#title' => ($i == 0 ? $this->t('Singular form') : $this->formatPlural($i, 'First plural form', '@count. plural form')),
103         '#default_value' => isset($plural_array[$i]) ? $plural_array[$i] : '',
104         '#description' => $this->t('Text to use for this variant, @count will be replaced with the value.'),
105         '#states' => [
106           'visible' => [
107             ':input[name="options[format_plural]"]' => ['checked' => TRUE],
108           ],
109         ],
110       ];
111     }
112     if ($plurals == 2) {
113       // Simplify interface text for the most common case.
114       $form['format_plural_values'][0]['#description'] = $this->t('Text to use for the singular form, @count will be replaced with the value.');
115       $form['format_plural_values'][1]['#title'] = $this->t('Plural form');
116       $form['format_plural_values'][1]['#description'] = $this->t('Text to use for the plural form, @count will be replaced with the value.');
117     }
118
119     $form['prefix'] = [
120       '#type' => 'textfield',
121       '#title' => $this->t('Prefix'),
122       '#default_value' => $this->options['prefix'],
123       '#description' => $this->t('Text to put before the number, such as currency symbol.'),
124     ];
125     $form['suffix'] = [
126       '#type' => 'textfield',
127       '#title' => $this->t('Suffix'),
128       '#default_value' => $this->options['suffix'],
129       '#description' => $this->t('Text to put after the number, such as currency symbol.'),
130     ];
131
132     parent::buildOptionsForm($form, $form_state);
133   }
134
135   /**
136    * {@inheritdoc}
137    */
138   public function submitOptionsForm(&$form, FormStateInterface $form_state) {
139     // Merge plural format options into one string and drop the individual
140     // option values.
141     $options = &$form_state->getValue('options');
142     $options['format_plural_string'] = implode(LOCALE_PLURAL_DELIMITER, $options['format_plural_values']);
143     unset($options['format_plural_values']);
144     parent::submitOptionsForm($form, $form_state);
145   }
146
147   /**
148    * {@inheritdoc}
149    */
150   public function render(ResultRow $values) {
151     $value = $this->getValue($values);
152
153     // Check to see if hiding should happen before adding prefix and suffix
154     // and before rewriting.
155     if ($this->options['hide_empty'] && empty($value) && ($value !== 0 || $this->options['empty_zero'])) {
156       return '';
157     }
158
159     if (!empty($this->options['set_precision'])) {
160       $precision = $this->options['precision'];
161     }
162     elseif ($decimal_position = strpos($value, '.')) {
163       $precision = strlen($value) - $decimal_position - 1;
164     }
165     else {
166       $precision = 0;
167     }
168
169     // Use round first to avoid negative zeros.
170     $value = round($value, $precision);
171     // Test against both integer zero and float zero.
172     if ($this->options['empty_zero'] && ($value === 0 || $value === 0.0)) {
173       return '';
174     }
175
176     $value = number_format($value, $precision, $this->options['decimal'], $this->options['separator']);
177
178     // If we should format as plural, take the (possibly) translated plural
179     // setting and format with the current language.
180     if (!empty($this->options['format_plural'])) {
181       $value = PluralTranslatableMarkup::createFromTranslatedString($value, $this->options['format_plural_string']);
182     }
183
184     return $this->sanitizeValue($this->options['prefix'], 'xss')
185       . $this->sanitizeValue($value)
186       . $this->sanitizeValue($this->options['suffix'], 'xss');
187   }
188
189 }