You are here

class GeneralNumberWithBarIndicatorFormatter in Formatter Suite 8

Presents an integer as a labeled horizontal bar of varying length.

Settings select the bar's color, the background color behind the bar, the bar's full length, and the bar's width. Optionally, the numeric value may be shown before or after the bar using the parent class's formatting.

The bar is drawn by creating a 1-pixel data URL of the chosen bar color.

Plugin annotation


@FieldFormatter(
  id          = "formatter_suite_general_number_with_bar_indicator",
  label       = @Translation("Formatter Suite - General number with bar indicator"),
  weight      = 1003,
  field_types = {
    "decimal",
    "float",
    "integer",
  }
)

Hierarchy

Expanded class hierarchy of GeneralNumberWithBarIndicatorFormatter

File

src/Plugin/Field/FieldFormatter/GeneralNumberWithBarIndicatorFormatter.php, line 33

Namespace

Drupal\formatter_suite\Plugin\Field\FieldFormatter
View source
class GeneralNumberWithBarIndicatorFormatter extends GeneralNumberFormatter {

  /*---------------------------------------------------------------------
   *
   * Configuration.
   *
   *---------------------------------------------------------------------*/

  /**
   * Returns an array of value locations.
   *
   * @return string[]
   *   Returns an associative array with internal names as keys and
   *   human-readable translated names as values.
   */
  protected static function getValueLocations() {
    return [
      'none' => t('No value'),
      'left' => t('Before bar'),
      'right' => t('After bar'),
    ];
  }

  /**
   * {@inheritdoc}
   */
  public static function defaultSettings() {
    return array_merge([
      'barLength' => '200',
      'barWidth' => '15',
      'barColor' => '#000000',
      'backgroundColor' => '#ffffff',
      'valueLocation' => 'right',
    ], parent::defaultSettings());
  }

  /**
   * {@inheritdoc}
   */
  public function settingsSummary() {
    $this
      ->sanitizeSettings();

    // Get current settings.
    $barLength = $this
      ->getSetting('barLength');
    $barWidth = $this
      ->getSetting('barWidth');
    $valueLocation = $this
      ->getSetting('valueLocation');
    $fieldSettings = $this
      ->getFieldSettings();
    $min = $fieldSettings['min'];
    $max = $fieldSettings['max'];

    // Sanitize & validate.
    $valueLocations = $this
      ->getValueLocations();
    if (empty($valueLocation) === TRUE || isset($valueLocations[$valueLocation]) === FALSE) {
      $valueLocation = 'none';
    }
    $disabledByMinMax = FALSE;
    $disabledByLength = FALSE;
    if (isset($min) === FALSE || isset($max) === FALSE) {
      $disabledByMinMax = TRUE;
    }
    elseif ($barLength <= 0 || $barWidth <= 0) {
      $disabledByLength = TRUE;
    }
    else {
      $barLength .= 'px';
      $barWidth .= 'px';
    }

    // Summarize.
    $summary = [];
    if ($disabledByMinMax === TRUE) {
      $summary[] = $this
        ->t('Disabled color bar, field min/max need to be set.');
      $summary = array_merge($summary, parent::settingsSummary());
    }
    elseif ($disabledByLength === TRUE) {
      $summary[] = $this
        ->t('Disabled color bar, bar size needs to be set.');
      $summary = array_merge($summary, parent::settingsSummary());
    }
    else {
      $summary[] = $this
        ->t('Colored bar @barLength long, @barWidth wide.', [
        '@barLength' => $barLength,
        '@barWidth' => $barWidth,
      ]);
      if ($valueLocation === 'none') {
        $summary[] = $this
          ->t('No value shown.');
      }
      else {
        $summary[] = $this
          ->t('Value @location.', [
          '@location' => $valueLocations[$valueLocation],
        ]);
        $summary = array_merge($summary, parent::settingsSummary());
      }
    }
    return $summary;
  }

  /*---------------------------------------------------------------------
   *
   * Settings form.
   *
   *---------------------------------------------------------------------*/

  /**
   * Returns a brief description of the formatter.
   *
   * @return string
   *   Returns a brief translated description of the formatter.
   */
  protected function getDescription() {
    return $this
      ->t('Draw a horizontal bar with a length based on the field value.');
  }

  /**
   * {@inheritdoc}
   */
  public function settingsForm(array $form, FormStateInterface $formState) {

    // Get the parent's form, which includes a lot of settings for
    // formatting numbers.
    $elements = parent::settingsForm($form, $formState);

    // Add warning if min/max are not set.
    $fieldSettings = $this
      ->getFieldSettings();
    $min = $fieldSettings['min'];
    $max = $fieldSettings['max'];
    $disabled = FALSE;
    if (isset($min) === FALSE || isset($max) === FALSE) {
      $disabled = TRUE;
      $elements['warning'] = [
        '#type' => 'html_tag',
        '#tag' => 'div',
        '#value' => $this
          ->t("To enable horizontal bar display, first set the minimum and maximum in the field's definition."),
        '#weight' => -999,
        '#attributes' => [
          'class' => [
            'formatter_suite-settings-warning',
          ],
        ],
      ];
    }
    $weight = 100;

    // Prompt for each setting.
    $elements['sectionBreak'] = [
      '#markup' => '<div class="formatter_suite-section-break"></div>',
      '#weight' => $weight++,
    ];
    $elements['barLength'] = [
      '#title' => $this
        ->t('Max bar length'),
      '#type' => 'number',
      '#min' => 1,
      '#max' => 5000,
      '#size' => 5,
      '#default_value' => $this
        ->getSetting('barLength'),
      '#disabled' => $disabled,
      '#weight' => $weight++,
      '#wrapper_attributes' => [
        'class' => [
          'formatter_suite-general-number-with-bar-indicator-bar-length',
        ],
      ],
    ];
    $elements['barWidth'] = [
      '#title' => $this
        ->t('Bar width'),
      '#type' => 'number',
      '#min' => 1,
      '#max' => 5000,
      '#size' => 5,
      '#default_value' => $this
        ->getSetting('barWidth'),
      '#description' => $this
        ->t('Bar length and width in pixels.'),
      '#disabled' => $disabled,
      '#weight' => $weight++,
      '#wrapper_attributes' => [
        'class' => [
          'formatter_suite-general-number-with-bar-indicator-bar-width',
        ],
      ],
    ];
    $elements['barColor'] = [
      '#title' => $this
        ->t('Bar color'),
      '#type' => 'textfield',
      '#size' => 7,
      '#default_value' => $this
        ->getSetting('barColor'),
      '#disabled' => $disabled,
      '#weight' => $weight++,
      '#attributes' => [
        'autocomplete' => 'off',
        'autocapitalize' => 'none',
        'spellcheck' => 'false',
        'autocorrect' => 'off',
      ],
      '#wrapper_attributes' => [
        'class' => [
          'formatter_suite-general-number-with-bar-indicator-bar-color',
        ],
      ],
    ];
    $elements['backgroundColor'] = [
      '#title' => $this
        ->t('Background color'),
      '#type' => 'textfield',
      '#size' => 7,
      '#default_value' => $this
        ->getSetting('backgroundColor'),
      '#description' => $this
        ->t("Colors use CSS syntax (e.g. '#ff0000'). Empty background uses page's background."),
      '#disabled' => $disabled,
      '#weight' => $weight++,
      '#attributes' => [
        'autocomplete' => 'off',
        'autocapitalize' => 'none',
        'spellcheck' => 'false',
        'autocorrect' => 'off',
      ],
      '#wrapper_attributes' => [
        'class' => [
          'formatter_suite-general-number-with-bar-indicator-background-color',
        ],
      ],
    ];
    $elements['valueLocation'] = [
      '#title' => $this
        ->t('Value location'),
      '#type' => 'select',
      '#options' => $this
        ->getValueLocations(),
      '#default_value' => $this
        ->getSetting('valueLocation'),
      '#disabled' => $disabled,
      '#weight' => $weight++,
      '#wrapper_attributes' => [
        'class' => [
          'formatter_suite-general-number-with-bar-indicator-value-location',
        ],
      ],
    ];
    return $elements;
  }

  /**
   * {@inheritdoc}
   */
  protected function sanitizeSettings() {

    // Get settings.
    $barLength = $this
      ->getSetting('barLength');
    $barWidth = $this
      ->getSetting('barWidth');
    $barColor = $this
      ->getSetting('barColor');
    $backgroundColor = $this
      ->getSetting('backgroundColor');
    $valueLocation = $this
      ->getSetting('valueLocation');
    $defaults = $this
      ->defaultSettings();

    // Sanitize & validate.
    parent::sanitizeSettings();
    $valueLocations = $this
      ->getValueLocations();
    if (empty($valueLocation) === TRUE || isset($valueLocations[$valueLocation]) === FALSE) {
      $valueLocation = $defaults['valueLocation'];
    }

    // Security: The bar length and weight have been entered by an
    // administrator. They both should be simple integers and should
    // not contain HTML or HTML entities.
    //
    // Parsing the values as integers ignores anything extra that
    // might be included in the value, such as spurious HTML.
    if (empty($barLength) === TRUE) {
      $barLength = intval($defaults['barLength']);
    }
    else {
      $barLength = intval($barLength);
      if ($barLength < 0) {
        $barLength = intval($defaults['barLength']);
      }
    }
    if (empty($barWidth) === TRUE) {
      $barWidth = intval($defaults['barWidth']);
    }
    else {
      $barWidth = intval($barWidth);
      if ($barWidth < 0) {
        $barWidth = intval($defaults['barWidth']);
      }
    }

    // Security: The bar and background colors have been entered by an
    // administrator. They both should be valid CSS colors of the form
    // #HEX.
    //
    // If a color doesn't start with '#', then it is illegal and we
    // revert to a default. Otherwise the color is escaped. The bar
    // color will be used to create an image, which will parse the
    // color. The background color will be included as an HTML attribute.
    if (empty($barColor) === TRUE || $barColor[0] !== '#') {
      $barColor = $defaults['barColor'];
    }
    else {
      $barColor = Html::escape($barColor);
    }
    if (empty($backgroundColor) === TRUE || $backgroundColor[0] !== '#') {
      $backgroundColor = $defaults['backgroundColor'];
    }
    else {
      $backgroundColor = Html::escape($backgroundColor);
    }
    $this
      ->setSetting('barLength', $barLength);
    $this
      ->setSetting('barWidth', $barWidth);
    $this
      ->setSetting('barColor', $barColor);
    $this
      ->setSetting('backgroundColor', $backgroundColor);
    $this
      ->setSetting('valueLocation', $valueLocation);
  }

  /*---------------------------------------------------------------------
   *
   * View.
   *
   *---------------------------------------------------------------------*/

  /**
   * {@inheritdoc}
   */
  public function viewElements(FieldItemListInterface $items, $langCode) {

    // The $items array has a list of items to format. We need to return
    // an array with identical indexing and corresponding render elements
    // for those items.
    if ($items
      ->isEmpty() === TRUE) {
      return [];
    }

    // Let the parent format all of the numbers first. This insures that
    // we have the parent's numeric formatting logic, including the use
    // of prefix and suffix, thousands marker, etc.
    //
    // This also sanitizes all settings.
    $build = parent::viewElements($items, $langCode);
    if (empty($build) === TRUE) {
      return [];
    }

    // Get current settings.
    $barColor = $this
      ->getSetting('barColor');
    $barLength = $this
      ->getSetting('barLength');
    $barWidth = $this
      ->getSetting('barWidth');
    $backgroundColor = $this
      ->getSetting('backgroundColor');
    $valueLocation = $this
      ->getSetting('valueLocation');
    $fieldSettings = $this
      ->getFieldSettings();
    $min = $fieldSettings['min'];
    $max = $fieldSettings['max'];
    if (empty($barLength) === TRUE || empty($barWidth) === TRUE || isset($min) === FALSE || isset($max) === FALSE) {

      // Missing bar size or field min/max needed to calculate bar length.
      // Disable bar. Just use the parent's formatting.
      return $build;
    }

    // Compute value range for converting values to percentages.
    $valueRange = (double) $max - (double) $min;

    // Create the bar, optionally with a value label.
    foreach ($items as $delta => $item) {

      // Calculate a percentage (0..1).
      $percent = ((double) $item->value - $min) / $valueRange;
      if ($percent < 0.0) {
        $percent = 0.0;
      }
      elseif ($percent > 1.0) {
        $percent = 1.0;
      }

      // Get the value label, if any.
      $valueLabel = '';
      if ($valueLocation !== 'none') {

        // Security: The numeric value to show beside the bar has already
        // been formatted by the parent class. It is known to be markup
        // so there is no further need to check it.
        //
        // Below, the value will be again added as markup, either before
        // or after the bar.
        $valueLabel = $build[$delta]['#markup'];
      }
      unset($build[$delta]['#markup']);

      // Create a container to include the label and bar.
      $build[$delta] = [
        '#type' => 'container',
        '#attributes' => [
          'class' => [
            'formatter_suite-general-number-with-bar-indicator-wrapper',
          ],
        ],
        '#attached' => [
          'library' => [
            'formatter_suite/formatter_suite.usage',
          ],
        ],
      ];

      // If the value label goes first, add it.
      if ($valueLocation === 'left') {
        $build[$delta]['value'] = [
          '#markup' => $valueLabel,
        ];
      }

      // Add the bar.
      //
      // Use inline styles because:
      // * The bar area length and width are parameters.
      // * The bar and background colors are parameters.
      $backgroundStyle = "width: {$barLength}px; height: {$barWidth}px;";
      if (empty($backgroundColor) === FALSE) {
        $backgroundStyle .= "background-color: {$backgroundColor};";
      }
      $build[$delta]['barouter'] = [
        '#type' => 'container',
        '#attributes' => [
          'class' => [
            'formatter_suite-general-number-with-bar-indicator-outer',
            'formatter_suite-general-number-with-bar-indicator-' . $valueLocation,
          ],
          'style' => $backgroundStyle,
        ],
        'bar' => [
          '#type' => 'html_tag',
          '#tag' => 'img',
          '#attributes' => [
            'class' => [
              'formatter_suite-general-number-with-bar-indicator',
            ],
            'src' => Utilities::createImage($barColor, $percent * $barLength, $barWidth),
          ],
        ],
      ];

      // If the value label goes last, add it.
      if ($valueLocation === 'right') {
        $build[$delta]['value'] = [
          '#markup' => $valueLabel,
        ];
      }
    }
    return $build;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
DependencySerializationTrait::$_entityStorages protected property An array of entity type IDs keyed by the property name of their storages.
DependencySerializationTrait::$_serviceIds protected property An array of service IDs keyed by property name used for serialization.
DependencySerializationTrait::__sleep public function 1
DependencySerializationTrait::__wakeup public function 2
FormatterBase::$fieldDefinition protected property The field definition.
FormatterBase::$label protected property The label display setting.
FormatterBase::$settings protected property The formatter settings. Overrides PluginSettingsBase::$settings
FormatterBase::$viewMode protected property The view mode.
FormatterBase::create public static function Creates an instance of the plugin. Overrides ContainerFactoryPluginInterface::create 11
FormatterBase::getFieldSetting protected function Returns the value of a field setting.
FormatterBase::getFieldSettings protected function Returns the array of field settings.
FormatterBase::isApplicable public static function Returns if the formatter can be used for the provided field. Overrides FormatterInterface::isApplicable 14
FormatterBase::prepareView public function Allows formatters to load information for field values being displayed. Overrides FormatterInterface::prepareView 2
FormatterBase::view public function Builds a renderable array for a fully themed field. Overrides FormatterInterface::view 1
FormatterBase::__construct public function Constructs a FormatterBase object. Overrides PluginBase::__construct 11
GeneralNumberFormatter::getDecimalSeparators protected static function Returns an array of decimal separators.
GeneralNumberFormatter::getExponentStyles protected static function Returns an array of scientific notation exponent styles.
GeneralNumberFormatter::getFieldPrefixes protected function Returns the array of field prefixes, if any.
GeneralNumberFormatter::getFieldSuffixes protected function Returns the array of field suffixes, if any.
GeneralNumberFormatter::getListStyles protected static function Returns an array of list styles.
GeneralNumberFormatter::getNegativeStyles protected static function Returns an array of negative styles.
GeneralNumberFormatter::getNotationStyles protected static function Returns an array of notation styles.
GeneralNumberFormatter::getPositiveStyles protected static function Returns an array of positive styles.
GeneralNumberFormatter::getThousandsSeparators protected static function Returns an array of thousands separators.
GeneralNumberFormatter::numberFormat protected function Format a number using the current settings. 1
GeneralNumberFormatter::numberFormatBasic protected function Formats a number using the basic set of formatting features.
GeneralNumberFormatter::numberFormatGeneral protected function Formats a number using the general set of formatting features.
GeneralNumberFormatter::numberFormatNumeral protected function Formats a number using a number system base.
GeneralNumberFormatter::numberFormatPercentage protected function Formats a number using a basic set of formatting features for percentages.
GeneralNumberFormatter::numberFormatScientific protected function Formats a number using scientific notation.
GeneralNumberFormatter::selectPrefix protected function Returns a prefix selected based on the value.
GeneralNumberFormatter::selectSuffix protected function Returns a suffix selected based on the value.
GeneralNumberWithBarIndicatorFormatter::defaultSettings public static function Defines the default settings for this plugin. Overrides GeneralNumberFormatter::defaultSettings
GeneralNumberWithBarIndicatorFormatter::getDescription protected function Returns a brief description of the formatter. Overrides GeneralNumberFormatter::getDescription
GeneralNumberWithBarIndicatorFormatter::getValueLocations protected static function Returns an array of value locations.
GeneralNumberWithBarIndicatorFormatter::sanitizeSettings protected function Sanitize settings to insure that they are safe and valid. Overrides GeneralNumberFormatter::sanitizeSettings
GeneralNumberWithBarIndicatorFormatter::settingsForm public function Returns a form to configure settings for the formatter. Overrides GeneralNumberFormatter::settingsForm
GeneralNumberWithBarIndicatorFormatter::settingsSummary public function Returns a short summary for the current formatter settings. Overrides GeneralNumberFormatter::settingsSummary
GeneralNumberWithBarIndicatorFormatter::viewElements public function Builds a renderable array for a field value. Overrides GeneralNumberFormatter::viewElements
MessengerTrait::$messenger protected property The messenger. 29
MessengerTrait::messenger public function Gets the messenger. 29
MessengerTrait::setMessenger public function Sets the messenger.
PluginBase::$configuration protected property Configuration information passed into the plugin. 1
PluginBase::$pluginDefinition protected property The plugin implementation definition. 1
PluginBase::$pluginId protected property The plugin_id.
PluginBase::DERIVATIVE_SEPARATOR constant A string which is used to separate base plugin IDs from the derivative ID.
PluginBase::getBaseId public function Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface::getBaseId
PluginBase::getDerivativeId public function Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface::getDerivativeId
PluginBase::getPluginDefinition public function Gets the definition of the plugin implementation. Overrides PluginInspectionInterface::getPluginDefinition 3
PluginBase::getPluginId public function Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface::getPluginId
PluginBase::isConfigurable public function Determines if the plugin is configurable.
PluginSettingsBase::$defaultSettingsMerged protected property Whether default settings have been merged into the current $settings.
PluginSettingsBase::$thirdPartySettings protected property The plugin settings injected by third party modules.
PluginSettingsBase::calculateDependencies public function Calculates dependencies for the configured plugin. Overrides DependentPluginInterface::calculateDependencies 6
PluginSettingsBase::getSetting public function Returns the value of a setting, or its default value if absent. Overrides PluginSettingsInterface::getSetting
PluginSettingsBase::getSettings public function Returns the array of settings, including defaults for missing settings. Overrides PluginSettingsInterface::getSettings
PluginSettingsBase::getThirdPartyProviders public function Gets the list of third parties that store information. Overrides ThirdPartySettingsInterface::getThirdPartyProviders
PluginSettingsBase::getThirdPartySetting public function Gets the value of a third-party setting. Overrides ThirdPartySettingsInterface::getThirdPartySetting
PluginSettingsBase::getThirdPartySettings public function Gets all third-party settings of a given module. Overrides ThirdPartySettingsInterface::getThirdPartySettings
PluginSettingsBase::mergeDefaults protected function Merges default settings values into $settings.
PluginSettingsBase::onDependencyRemoval public function Informs the plugin that some configuration it depends on will be deleted. Overrides PluginSettingsInterface::onDependencyRemoval 3
PluginSettingsBase::setSetting public function Sets the value of a setting for the plugin. Overrides PluginSettingsInterface::setSetting
PluginSettingsBase::setSettings public function Sets the settings for the plugin. Overrides PluginSettingsInterface::setSettings
PluginSettingsBase::setThirdPartySetting public function Sets the value of a third-party setting. Overrides ThirdPartySettingsInterface::setThirdPartySetting
PluginSettingsBase::unsetThirdPartySetting public function Unsets a third-party setting. Overrides ThirdPartySettingsInterface::unsetThirdPartySetting
StringTranslationTrait::$stringTranslation protected property The string translation service. 1
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.