datafield-1.x-dev/src/Plugin/DataField/FieldWidget/NumberFormatWidget.php

src/Plugin/DataField/FieldWidget/NumberFormatWidget.php
<?php

namespace Drupal\datafield\Plugin\DataField\FieldWidget;

use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Field\Attribute\FieldWidget;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Plugin implementation of the 'number format' widget.
 */
#[FieldWidget(
  id: 'number_format',
  label: new TranslatableMarkup('Number format'),
  field_types: ['integer', 'numeric', 'float'],
)]
class NumberFormatWidget extends NumberWidget implements ContainerFactoryPluginInterface {
  use StringTranslationTrait;

  /**
   * Constructs a EntityReferenceAutocompleteWidget object.
   *
   * @param string $plugin_id
   *   The plugin_id for the formatter.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param mixed $field_definition
   *   The definition of the field to which the formatter is associated.
   * @param \Drupal\Core\Session\AccountInterface $currentUser
   *   The current user.
   */
  public function __construct($plugin_id, $plugin_definition, $field_definition, protected AccountInterface $currentUser) {
    unset($plugin_id, $plugin_definition, $field_definition);
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $plugin_id,
      $plugin_definition,
      $configuration,
      $container->get('current_user'),
    );
  }

  /**
   * {@inheritdoc}
   */
  public function getFormElement(&$element, $item = NULL, $setting = []) {
    parent::getFormElement($element, $item, $setting);
    // Add validate process width numeric field.
    $element['#element_validate'] = [[$this, 'validate']];
    $limit = $this->getLimitNumber($element['#field_storage'], $element['#field_storage']['type'], !empty($element['#field_storage']['unsigned']));
    $min = $limit ? $limit['min'] : $element['#field_settings']['min'];
    if ($element['#field_settings']['min'] && $limit['min']) {
      $min = max($element['#field_settings']['min'], $limit['min']);
    }
    if ($min !== NULL) {
      $element['#attributes']['min'] = $min;
    }
    $max = $limit ? $limit['max'] : $element['#field_settings']['max'];
    if ($element['#field_settings']['max'] && $limit['min']) {
      $max = min($element['#field_settings']['max'], $limit['max']);
    }
    if ($max !== NULL) {
      $element['#attributes']['max'] = $max;
    }
    if (array_key_exists('scale', $element['#field_storage'])) {
      $element['#attributes']['scale'] = $element['#field_storage']['scale'];
    }
    $element['#attributes']['field_type'] = $element['#field_storage']['type'];
    $element['#type'] = 'textfield';
    $element['#attributes']['class'][] = 'text-format-number';
    $element['#attached']['library'][] = 'datafield/auto_numeric';
    $element['#attached']['library'][] = 'datafield/formatnumber';
    $element['#attached']['drupalSettings']['auto_numeric']['language'] = $this->getLanguage();
    return $element;
  }

  /**
   * {@inheritdoc}
   */
  protected function getLanguage(): string {
    $languageId = $this->currentUser->getPreferredLangcode();
    $language = 'British';
    $formatNum = [
      'French' => ['fr', 'af', 'ar', 'be', 'bg', 'br', 'cs', 'eo', 'et', 'fi',
        'ht', 'hu', 'hy', 'ka', 'kk', 'ky', 'lt', 'lv', 'mg', 'nb', 'nn', 'oc',
        'os', 'pl', 'prs', 'ps', 'pt', 'pt-pt', 'ru', 'rw', 'se', 'sk', 'sq',
        'sv', 'tyv', 'uk',
      ],
      'Spanish' => ['de', 'ast', 'az', 'bs', 'ca', 'da', 'el', 'es', 'eu', 'fo',
        'fy', 'gl', 'hr', 'id', 'is', 'it', 'jv', 'ku', 'mk', 'nl', 'pt-br',
        'ro', 'sl', 'sr', 'tr', 'vi',
      ],
    ];
    foreach ($formatNum as $lang => $languageIso) {
      if (in_array($languageId, $languageIso)) {
        $language = $lang;
        break;
      }
    }
    return $language;
  }

  /**
   * {@inheritdoc}
   */
  protected function getLimitNumber($field_settings, $field_type, $unsigned = FALSE) {
    $int_limits = [
      'signed' => [
        'big' => ['min' => PHP_INT_MIN, 'max' => PHP_INT_MAX],
        'normal' => ['min' => -2147483648, 'max' => 2147483647],
        'medium' => ['min' => -8388608, 'max' => 8388607],
        'small' => ['min' => -32768, 'max' => 32767],
        'tiny' => ['min' => -128, 'max' => 127],
      ],
      'unsigned' => [
        'big' => ['min' => 0, 'max' => 18446744073709551615],
        'normal' => ['min' => 0, 'max' => 4294967295],
        'medium' => ['min' => 0, 'max' => 16777215],
        'small' => ['min' => 0, 'max' => 65535],
        'tiny' => ['min' => 0, 'max' => 255],
      ],
    ];
    if ($field_type === 'int' || $field_type === 'integer') {
      return $int_limits[$unsigned ? 'unsigned' : 'signed'][$field_settings['size']] ?? FALSE;
    }
    if (in_array($field_type, ['float', 'numeric'], TRUE) && isset($field_settings['precision'], $field_settings['scale'])) {
      $value_allow = str_repeat('9', $field_settings['precision'] - $field_settings['scale']) . '.' . str_repeat('9', $field_settings['scale']);
      return ['min' => "-$value_allow", 'max' => $value_allow];
    }
    return FALSE;
  }

  /**
   * Validate the numeric field.
   */
  public function validate(&$element, FormStateInterface &$form_state, &$complete_form): void {
    $limit = $this->getLimitNumber($element['#field_storage'], $element['#field_storage']['type'], !empty($element['#field_storage']['unsigned']));
    $value = $element['#value'];
    $user_input = $form_state->getUserInput();
    $lang = $this->getLanguage();
    switch ($lang) {
      case 'Spanish':
      case 'French':
        $separator = '.';
        $decimal_character = ',';
        $value = str_replace('.', '', $value);
        $value = str_replace(',', '.', $value);
        break;
    }
    $value = preg_replace('/(?!^-)[^\d.]/', '', $value);

    if ($value !== '' && $limit) {
      if ($value < $limit['min'] || $value > $limit['max']) {
        $number_format = new \NumberFormatter($lang, \NumberFormatter::DECIMAL);
        $number_format->setSymbol(\NumberFormatter::GROUPING_SEPARATOR_SYMBOL, $separator ?? ',');
        $number_format->setSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL, $decimal_character ?? '.');
        if ($value < $limit['min']) {
          $arg = [
            '@field' => $element['#field_settings']['label'],
            '@limit_value' => $number_format->format($limit['min']),
          ];
        }
        else {
          $arg = [
            '@field' => $element['#field_settings']['label'],
            '@limit_value' => $number_format->format($limit['max']),
          ];
        }
        $form_state->setError($element, $this->t('@field numeric value out of range @limit_value.', $arg));
        return;
      }
    }

    $element['#value'] = $value;
    $form_state->setValueForElement($element, $value);

    if (!empty($element['#parents']) && count($element['#parents']) > 1) {
      NestedArray::setValue($user_input, $element['#parents'], $value);
    }
    else {
      $user_input[$element['#field_name']][$element['#delta']][$element['#machine_name']] = $value;
    }
    $form_state->setUserInput($user_input);
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc