Skip to content

Commit

Permalink
feat: Differentiate between kilobyte/kibibyte and megabyte/mebibyte (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
ThomasMeschke authored Dec 4, 2024
1 parent 35c5784 commit 455a559
Show file tree
Hide file tree
Showing 7 changed files with 190 additions and 4 deletions.
41 changes: 38 additions & 3 deletions system/Files/File.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,17 +70,39 @@ public function getSize()
return $this->size ?? ($this->size = parent::getSize());
}

/**
* Retrieve the file size by unit, calculated in IEC standards with 1024 as base value.
*
* @phpstan-param positive-int $precision
*/
public function getSizeByBinaryUnit(FileSizeUnit $unit = FileSizeUnit::B, int $precision = 3): int|string
{
return $this->getSizeByUnitInternal(1024, $unit, $precision);
}

/**
* Retrieve the file size by unit, calculated in metric standards with 1000 as base value.
*
* @phpstan-param positive-int $precision
*/
public function getSizeByMetricUnit(FileSizeUnit $unit = FileSizeUnit::B, int $precision = 3): int|string
{
return $this->getSizeByUnitInternal(1000, $unit, $precision);
}

/**
* Retrieve the file size by unit.
*
* @deprecated 4.6.0 Use getSizeByBinaryUnit() or getSizeByMetricUnit() instead
*
* @return false|int|string
*/
public function getSizeByUnit(string $unit = 'b')
{
return match (strtolower($unit)) {
'kb' => number_format($this->getSize() / 1024, 3),
'mb' => number_format(($this->getSize() / 1024) / 1024, 3),
default => $this->getSize(),
'kb' => $this->getSizeByBinaryUnit(FileSizeUnit::KB),
'mb' => $this->getSizeByBinaryUnit(FileSizeUnit::MB),
default => $this->getSize()
};
}

Expand Down Expand Up @@ -189,4 +211,17 @@ public function getDestination(string $destination, string $delimiter = '_', int

return $destination;
}

private function getSizeByUnitInternal(int $fileSizeBase, FileSizeUnit $unit, int $precision): int|string
{
$exponent = $unit->value;
$divider = $fileSizeBase ** $exponent;
$size = $this->getSize() / $divider;

if ($unit !== FileSizeUnit::B) {
$size = number_format($size, $precision);
}

return $size;
}
}
42 changes: 42 additions & 0 deletions system/Files/FileSizeUnit.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

declare(strict_types=1);

/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <[email protected]>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

namespace CodeIgniter\Files;

use CodeIgniter\Exceptions\InvalidArgumentException;

enum FileSizeUnit: int
{
case B = 0;
case KB = 1;
case MB = 2;
case GB = 3;
case TB = 4;

/**
* Allows the creation of a FileSizeUnit from Strings like "kb" or "mb"
*
* @throws InvalidArgumentException
*/
public static function fromString(string $unit): self
{
return match (strtolower($unit)) {
'b' => self::B,
'kb' => self::KB,
'mb' => self::MB,
'gb' => self::GB,
'tb' => self::TB,
default => throw new InvalidArgumentException("Invalid unit: {$unit}"),
};
}
}
54 changes: 54 additions & 0 deletions tests/system/Files/FileTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

use CodeIgniter\Files\Exceptions\FileNotFoundException;
use CodeIgniter\Test\CIUnitTestCase;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Group;
use ZipArchive;

Expand Down Expand Up @@ -113,6 +114,38 @@ public function testGetSizeReturnsBytes(): void
$this->assertSame($size, $file->getSizeByUnit('b'));
}

#[DataProvider('provideGetSizeData')]
public function testGetSizeBinary(FileSizeUnit $unit): void
{
$divider = 1024 ** $unit->value;
$file = new File(SYSTEMPATH . 'Common.php');
$size = number_format(filesize(SYSTEMPATH . 'Common.php') / $divider, 3);
$this->assertSame($size, $file->getSizeByBinaryUnit($unit));
}

public function testGetSizeBinaryBytes(): void
{
$file = new File(SYSTEMPATH . 'Common.php');
$size = filesize(SYSTEMPATH . 'Common.php');
$this->assertSame($size, $file->getSizeByBinaryUnit(FileSizeUnit::B));
}

#[DataProvider('provideGetSizeData')]
public function testGetSizeMetric(FileSizeUnit $unit): void
{
$divider = 1000 ** $unit->value;
$file = new File(SYSTEMPATH . 'Common.php');
$size = number_format(filesize(SYSTEMPATH . 'Common.php') / $divider, 3);
$this->assertSame($size, $file->getSizeByMetricUnit($unit));
}

public function testGetSizeMetricBytes(): void
{
$file = new File(SYSTEMPATH . 'Common.php');
$size = filesize(SYSTEMPATH . 'Common.php');
$this->assertSame($size, $file->getSizeByMetricUnit(FileSizeUnit::B));
}

public function testThrowsExceptionIfNotAFile(): void
{
$this->expectException(FileNotFoundException::class);
Expand All @@ -135,4 +168,25 @@ public function testGetDestination(): void
unlink(SYSTEMPATH . 'Common_Copy.php');
unlink(SYSTEMPATH . 'Common_Copy_5.php');
}

/**
* @return array<string, array<int, FileSizeUnit>>
*/
public static function provideGetSizeData()
{
return [
'returns KB binary' => [
FileSizeUnit::KB,
],
'returns MB binary' => [
FileSizeUnit::MB,
],
'returns GB binary' => [
FileSizeUnit::GB,
],
'returns TB binary' => [
FileSizeUnit::TB,
],
];
}
}
5 changes: 5 additions & 0 deletions user_guide_src/source/changelogs/v4.6.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,8 @@ Model
Libraries
=========

- **File:** Added ``getSizeByBinaryUnit()`` and ``getSizeByMetricUnit()`` to ``File`` class.
See :ref:`File::getSizeByBinaryUnit() <file-get-size-by-binary-unit>` and :ref:`File::getSizeByMetricUnit() <file-get-size-by-metric-unit>`.
- **FileCollection:** Added ``retainMultiplePatterns()`` to ``FileCollection`` class.
See :ref:`FileCollection::retainMultiplePatterns() <file-collections-retain-multiple-patterns>`.
- **Validation:** Added ``min_dims`` validation rule to ``FileRules`` class. See
Expand Down Expand Up @@ -286,6 +288,9 @@ Deprecations
- The properties ``$arguments`` and ``$argumentsClass`` of ``Filters`` have
been deprecated. No longer used.
- The ``Filters::getArguments()`` method has been deprecated. No longer used.
- **File:**
- The function ``getSizeByUnit()`` of ``File`` has been deprecated.
Use either ``getSizeByBinaryUnit()`` or ``getSizeByMetricUnit()`` instead.

**********
Bugs Fixed
Expand Down
38 changes: 37 additions & 1 deletion user_guide_src/source/libraries/files.rst
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,50 @@ A ``RuntimeException`` will be thrown if the file does not exist or an error occ
getSizeByUnit()
===============

.. deprecated:: 4.6.0

Returns the size of the file default in bytes. You can pass in either ``'kb'`` or ``'mb'`` as the first parameter to get
the results in kilobytes or megabytes, respectively:
the results in kibibytes or mebibytes, respectively:

.. literalinclude:: files/005.php
:lines: 2-

A ``RuntimeException`` will be thrown if the file does not exist or an error occurs.


.. _file-get-size-by-binary-unit:

getSizeByBinaryUnit()
=====================

.. versionadded:: 4.6.0

Returns the size of the file default in bytes. You can pass in different FileSizeUnit values as the first parameter to get
the results in kibibytes, mebibytes etc. respectively. You can pass in a precision value as the second parameter to define
the amount of decimal places.

.. literalinclude:: files/017.php
:lines: 4-

A ``RuntimeException`` will be thrown if the file does not exist or an error occurs.


.. _file-get-size-by-metric-unit:

getSizeByMetricUnit()
=====================

.. versionadded:: 4.6.0

Returns the size of the file default in bytes. You can pass in different FileSizeUnit values as the first parameter to get
the results in kilobytes, megabytes etc. respectively. You can pass in a precision value as the second parameter to define
the amount of decimal places.

.. literalinclude:: files/018.php
:lines: 4-

A ``RuntimeException`` will be thrown if the file does not exist or an error occurs.

getMimeType()
=============

Expand Down
7 changes: 7 additions & 0 deletions user_guide_src/source/libraries/files/017.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

use CodeIgniter\Files\FileSizeUnit;

$bytes = $file->getSizeByBinaryUnit(); // 256901
$kibibytes = $file->getSizeByBinaryUnit(FileSizeUnit::KB); // 250.880
$mebibytes = $file->getSizeByBinaryUnit(FileSizeUnit::MB); // 0.245
7 changes: 7 additions & 0 deletions user_guide_src/source/libraries/files/018.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

use CodeIgniter\Files\FileSizeUnit;

$bytes = $file->getSizeByMetricUnit(); // 256901
$kilobytes = $file->getSizeByMetricUnit(FileSizeUnit::KB); // 256.901
$megabytes = $file->getSizeByMetricUnit(FileSizeUnit::MB); // 0.256

0 comments on commit 455a559

Please sign in to comment.