From d2ff08e0dcb8241800da7122d16c991cb98b0543 Mon Sep 17 00:00:00 2001 From: Alex Pott Date: Mon, 2 Feb 2015 11:09:18 +0000 Subject: [PATCH] Issue #2395613 by dawehner: Make it possible to configure the output of a boolean field on the formatter level --- core/config/schema/core.entity.schema.yml | 13 ++ .../Field/FieldFormatter/BooleanFormatter.php | 98 +++++++++++- .../Tests/Boolean/BooleanFormatterTest.php | 144 ++++++++++++++++++ 3 files changed, 253 insertions(+), 2 deletions(-) create mode 100644 core/modules/field/src/Tests/Boolean/BooleanFormatterTest.php diff --git a/core/config/schema/core.entity.schema.yml b/core/config/schema/core.entity.schema.yml index 2d1b7dc5543..ee3d5d78285 100644 --- a/core/config/schema/core.entity.schema.yml +++ b/core/config/schema/core.entity.schema.yml @@ -222,6 +222,19 @@ field.widget.settings.checkbox: type: boolean label: 'Use field label instead of the "On value" as label' +field.formatter.settings.boolean: + type: mapping + mapping: + format: + type: string + label: 'Output format' + format_custom_false: + type: string + label: 'Custom output for FALSE' + format_custom_true: + type: string + label: 'Custom output for TRUE' + field.formatter.settings.string: type: mapping mapping: diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/BooleanFormatter.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/BooleanFormatter.php index 6860dee19cb..11164b4fe38 100644 --- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/BooleanFormatter.php +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/BooleanFormatter.php @@ -9,6 +9,7 @@ namespace Drupal\Core\Field\Plugin\Field\FieldFormatter; use Drupal\Core\Field\FormatterBase; use Drupal\Core\Field\FieldItemListInterface; +use Drupal\Core\Form\FormStateInterface; /** * Plugin implementation of the 'boolean' formatter. @@ -23,14 +24,107 @@ use Drupal\Core\Field\FieldItemListInterface; */ class BooleanFormatter extends FormatterBase { + /** + * {@inheritdoc} + */ + public static function defaultSettings() { + $settings = []; + + // Fall back to field settings by default. + $settings['format'] = 'default'; + $settings['format_custom_false'] = ''; + $settings['format_custom_true'] = ''; + + return $settings; + } + + /** + * Gets the available format options. + * + * @return array|string + * A list of output formats. Each entry is keyed by the machine name of the + * format. The value is an array, of which the first item is the result for + * boolean TRUE, the second is for boolean FALSE. The value can be also an + * array, but this is just the case for the custom format. + */ + protected function getOutputFormats() { + $formats = [ + 'default' => [$this->getFieldSetting('on_label'), $this->getFieldSetting('off_label')], + 'yes-no' => [$this->t('Yes'), $this->t('No')], + 'true-false' => [$this->t('True'), $this->t('False')], + 'on-off' => [$this->t('On'), $this->t('Off')], + 'enabled-disabled' => [$this->t('Enabled'), $this->t('Disabled')], + 'boolean' => [1, 0], + 'unicode-yes-no' => ['✔', '✖'], + 'custom' => $this->t('Custom'), + ]; + + return $formats; + } + + /** + * {@inheritdoc} + */ + public function settingsForm(array $form, FormStateInterface $form_state) { + $form = parent::settingsForm($form, $form_state); + + $formats = []; + foreach ($this->getOutputFormats() as $format_name => $format) { + if (is_array($format)) { + $formats[$format_name] = implode(' / ', $format); + } + else { + $formats[$format_name] = $format; + } + } + + $form['format'] = [ + '#type' => 'select', + '#title' => $this->t('Output format'), + '#default_value' => $this->getSetting('format'), + '#options' => $formats, + ]; + $form['format_custom_true'] = [ + '#type' => 'textfield', + '#title' => $this->t('Custom output for TRUE'), + '#default_value' => $this->getSetting('format_custom_true'), + '#states' => [ + 'visible' => [ + 'select[name="fields[field_boolean][settings_edit_form][settings][format]"]' => ['value' => 'custom'], + ], + ], + ]; + $form['format_custom_false'] = [ + '#type' => 'textfield', + '#title' => $this->t('Custom output for FALSE'), + '#default_value' => $this->getSetting('format_custom_false'), + '#states' => [ + 'visible' => [ + 'select[name="fields[field_boolean][settings_edit_form][settings][format]"]' => ['value' => 'custom'], + ], + ], + ]; + + return $form; + } + /** * {@inheritdoc} */ public function viewElements(FieldItemListInterface $items) { - $elements = array(); + $elements = []; + + $formats = $this->getOutputFormats(); foreach ($items as $delta => $item) { - $elements[$delta] = array('#markup' => $item->value ? $this->getFieldSetting('on_label') : $this->getFieldSetting('off_label')); + $format = $this->getSetting('format'); + + if ($format == 'custom') { + $elements[$delta] = ['#markup' => $item->value ? $this->getSetting('format_custom_true') : $this->getSetting('format_custom_false')]; + } + else { + $elements[$delta] = ['#markup' => $item->value ? $formats[$format][0] : $formats[$format][1]]; + } } return $elements; diff --git a/core/modules/field/src/Tests/Boolean/BooleanFormatterTest.php b/core/modules/field/src/Tests/Boolean/BooleanFormatterTest.php new file mode 100644 index 00000000000..214590d818f --- /dev/null +++ b/core/modules/field/src/Tests/Boolean/BooleanFormatterTest.php @@ -0,0 +1,144 @@ +installConfig(['field']); + $this->installEntitySchema('entity_test'); + + $this->entityType = 'entity_test'; + $this->bundle = $this->entityType; + $this->fieldName = Unicode::strtolower($this->randomMachineName()); + + $field_storage = FieldStorageConfig::create([ + 'field_name' => $this->fieldName, + 'entity_type' => $this->entityType, + 'type' => 'boolean', + ]); + $field_storage->save(); + + $instance = FieldConfig::create([ + 'field_storage' => $field_storage, + 'bundle' => $this->bundle, + 'label' => $this->randomMachineName(), + ]); + $instance->save(); + + $this->display = entity_get_display($this->entityType, $this->bundle, 'default') + ->setComponent($this->fieldName, [ + 'type' => 'boolean', + 'settings' => [], + ]); + $this->display->save(); + } + + /** + * Renders fields of a given entity with a given display. + * + * @param \Drupal\Core\Entity\FieldableEntityInterface $entity + * The entity object with attached fields to render. + * @param \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display + * The display to render the fields in. + * + * @return string + * The rendered entity fields. + */ + protected function renderEntityFields(FieldableEntityInterface $entity, EntityViewDisplayInterface $display) { + $content = $display->build($entity); + $content = $this->render($content); + return $content; + } + + /** + * Tests boolean formatter output. + */ + public function testBooleanFormatter() { + $data = []; + $data[] = [0, [], 'Off']; + $data[] = [1, [], 'On']; + + $format = ['format' => 'enabled-disabled']; + $data[] = [0, $format, 'Disabled']; + $data[] = [1, $format, 'Enabled']; + + $format = ['format' => 'unicode-yes-no']; + $data[] = [1, $format, '✔']; + $data[] = [0, $format, '✖']; + + $format = [ + 'format' => 'custom', + 'format_custom_false' => 'FALSE', + 'format_custom_true' => 'TRUE' + ]; + $data[] = [0, $format, 'FALSE']; + $data[] = [1, $format, 'TRUE']; + + foreach ($data as $test_data) { + list($value, $settings, $expected) = $test_data; + + $component = $this->display->getComponent($this->fieldName); + $component['settings'] = $settings; + $this->display->setComponent($this->fieldName, $component); + + $entity = EntityTest::create([]); + $entity->{$this->fieldName}->value = $value; + + // Verify that all HTML is escaped and newlines are retained. + $this->renderEntityFields($entity, $this->display); + $this->assertRaw($expected); + } + } + +}