You are here

public static function Utilities::formatBytes in Formatter Suite 8

Formats a number with a bytes suffix.

@internal Drupal's format_size() function is widely used to format values in units of kilobytes, megabytes, etc. Unfortunately, it considers a "kilobyte" equal to 1024 bytes, which is not compliant with the 1998 International Electrotechnical Commission (IEC) and International System of Quantities (ISO) standards. By those standards, a "kilobyte" equals 1000 bytes. This definition retains the SI units convention that "k" is for 1000 (e.g. kilometer, kilogram).

The following code is loosely based upon format_size(). It corrects the math for the selected "k" units (kilo or kibi) and uses the corresponding correct suffixes. It also supports a requested number of decimal digits.

The following code also ignores the $langcode, which format_size() incorrectly uses to make the output translatable - even though it is NOT subject to translation since it is numeric and the suffixes are defined by international standards. @endinternal

Parameters

mixed $number: The number to format.

int $kunit: (optional, default = 1000) Either 1000 (ISO standard kilobyte) or 1024 (legacy kibibyte).

bool $fullWord: (optional, default = FALSE) When FALSE, use an abbreviation suffix, like "KB". When TRUE, use a full word suffix, like "Kilobytes".

int $decimalDigits: (optional, default = 2) The number of decimal digits for the resulting number.

Return value

\Drupal\Core\StringTranslation\TranslatableMarkup Returns a representation of the number, along with a suffix that summarizes the value using the selected 'k' units.

4 calls to Utilities::formatBytes()
GeneralFileLinkFormatter::viewElements in src/Plugin/Field/FieldFormatter/GeneralFileLinkFormatter.php
Builds a renderable array for a field value.
GeneralImageFormatter::viewElements in src/Plugin/Field/FieldFormatter/GeneralImageFormatter.php
Builds a renderable array for a field value.
NumberWithBytesFormatter::settingsSummary in src/Plugin/Field/FieldFormatter/NumberWithBytesFormatter.php
Returns a short summary for the current formatter settings.
NumberWithBytesFormatter::viewElements in src/Plugin/Field/FieldFormatter/NumberWithBytesFormatter.php
Builds a renderable array for a field value.

File

src/Utilities.php, line 111

Class

Utilities
Defines utility functions used throughout the module.

Namespace

Drupal\formatter_suite

Code

public static function formatBytes($number, int $kunit = 1000, bool $fullWord = FALSE, int $decimalDigits = 2) {

  // Validate.
  switch ($kunit) {
    case 1000:
    case 1024:
      $kunit = (double) $kunit;
      break;
    default:
      $kunit = 1000.0;
      break;
  }
  if ($decimalDigits < 0) {
    $decimalDigits = 0;
  }
  if ($number < $kunit) {

    // The quantity is smaller than the 'k' unit. Report it as-is.
    return \Drupal::translation()
      ->formatPlural($number, '1 byte', '@count bytes');
  }

  // Find the proper 'k'. Values larger than the largest 'k' unit
  // will just be large numbers ahead of the largest prefix (e.g.
  // "879 YB").
  $value = (double) $number / $kunit;
  foreach ([
    'K',
    'M',
    'G',
    'T',
    'P',
    'E',
    'Z',
    'Y',
  ] as $unit) {
    if ($value < $kunit) {

      // The value is now less than the next unit, stop reducing.
      break;
    }
    $value /= $kunit;
  }

  // Simplify the remainder with the proper number of decimal digits.
  $fmt = '%1.' . $decimalDigits . 'f';
  $formattedValue = sprintf($fmt, $value);

  // If using abbrevations, return the formatted value and suffix.
  if ($fullWord === FALSE) {

    // Use abbreviations for suffixes.
    switch ($kunit) {
      default:
      case 1000:
        $suffix = $unit . 'B';
        break;
      case 1024:
        $suffix = $unit . 'iB';
        break;
    }
    return new FormattableMarkup('@value @suffix', [
      '@value' => $formattedValue,
      '@suffix' => $suffix,
    ]);
  }

  // When using full words, return the formatted value and word,
  // using singular and plural forms as appropriate.
  $singular = [];
  $plural = [];
  switch ($kunit) {
    default:
    case 1000:
      $singular = [
        'K' => 'Kilobyte',
        'M' => 'Megabyte',
        'G' => 'Gigabyte',
        'T' => 'Terabyte',
        'P' => 'Petabyte',
        'E' => 'Exabyte',
        'Z' => 'Zettabyte',
        'Y' => 'Yottabyte',
      ];
      $plural = [
        'K' => 'Kilobytes',
        'M' => 'Megabytes',
        'G' => 'Gigabytes',
        'T' => 'Terabytes',
        'P' => 'Petabytes',
        'E' => 'Exabytes',
        'Z' => 'Zettabytes',
        'Y' => 'Yottabytes',
      ];
      break;
    case 1024:
      $singular = [
        'K' => 'Kibibyte',
        'M' => 'Mibibyte',
        'G' => 'Gibibyte',
        'T' => 'Tebibyte',
        'P' => 'Pebibyte',
        'E' => 'Exbibyte',
        'Z' => 'Zebibyte',
        'Y' => 'Yobibyte',
      ];
      $plural = [
        'K' => 'Kibibytes',
        'M' => 'Mibibytes',
        'G' => 'Gibibytes',
        'T' => 'Tebibytes',
        'P' => 'Pebibytes',
        'E' => 'Exbibytes',
        'Z' => 'Zebibytes',
        'Y' => 'Yobibytes',
      ];
      break;
  }
  return new FormattableMarkup('@value @suffix', [
    '@value' => $formattedValue,
    '@suffix' => $value < 1 ? $singular[$unit] : $plural[$unit],
  ]);
}