From 857da2a56ac6f66b2682fc5a1db8b3e166da324f Mon Sep 17 00:00:00 2001 From: Thomas Meschke Date: Tue, 12 Nov 2024 13:44:40 +0100 Subject: [PATCH] refactor: differentiate between kilo/kibibytes and mega/mebibytes --- system/Files/File.php | 43 +++++++++++++-- system/Files/FileSizeUnit.php | 23 ++++++++ tests/system/Files/FileTest.php | 54 +++++++++++++++++++ user_guide_src/source/changelogs/v4.6.0.rst | 3 ++ user_guide_src/source/libraries/files.rst | 28 +++++++++- user_guide_src/source/libraries/files/017.php | 5 ++ user_guide_src/source/libraries/files/018.php | 5 ++ 7 files changed, 157 insertions(+), 4 deletions(-) create mode 100644 system/Files/FileSizeUnit.php create mode 100644 user_guide_src/source/libraries/files/017.php create mode 100644 user_guide_src/source/libraries/files/018.php diff --git a/system/Files/File.php b/system/Files/File.php index 15b53262e9c2..e36f24ac7529 100644 --- a/system/Files/File.php +++ b/system/Files/File.php @@ -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. + * + * @return false|int|string + */ + public function getSizeByUnitBinary(FileSizeUnit $unit = FileSizeUnit::B, int $precision = 3) + { + return $this->getSizeByUnitInternal(1024, $unit, $precision); + } + + /** + * Retrieve the file size by unit, calculated in metric standards with 1000 as base value. + * + * @return false|int|string + */ + public function getSizeByUnitMetric(FileSizeUnit $unit = FileSizeUnit::B, int $precision = 3) + { + return $this->getSizeByUnitInternal(1000, $unit, $precision); + } + /** * Retrieve the file size by unit. * + * @deprecated Use getSizeByUnitBinary or getSizeByUnitMetric 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->getSizeByUnitBinary(FileSizeUnit::KB), + 'mb' => $this->getSizeByUnitBinary(FileSizeUnit::MB), + default => $this->getSizeByUnitBinary(FileSizeUnit::B) }; } @@ -189,4 +211,19 @@ public function getDestination(string $destination, string $delimiter = '_', int return $destination; } + + protected function getSizeByUnitInternal(int $fileSizeBase, FileSizeUnit $unit, int $precision) + { + $exponent = $unit->value; + $divider = pow($fileSizeBase, $exponent); + + $size = $this->getSize() / $divider; + + if($unit !== FileSizeUnit::B) + { + $size = number_format($size, $precision); + } + + return $size; + } } diff --git a/system/Files/FileSizeUnit.php b/system/Files/FileSizeUnit.php new file mode 100644 index 000000000000..8f30eeb00d8f --- /dev/null +++ b/system/Files/FileSizeUnit.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace CodeIgniter\Files; + +enum FileSizeUnit : int +{ + case B = 0; + case KB = 1; + case MB = 2; + case GB = 3; + case TB = 4; +} \ No newline at end of file diff --git a/tests/system/Files/FileTest.php b/tests/system/Files/FileTest.php index 800a1ac278f1..9b608647a583 100644 --- a/tests/system/Files/FileTest.php +++ b/tests/system/Files/FileTest.php @@ -113,6 +113,42 @@ public function testGetSizeReturnsBytes(): void $this->assertSame($size, $file->getSizeByUnit('b')); } + /** + * @dataProvider provideGetSizeData + */ + public function testGetSizeBinary(FileSizeUnit $unit): void + { + $divider = pow(1024, $unit->value); + $file = new File(SYSTEMPATH . 'Common.php'); + $size = number_format(filesize(SYSTEMPATH . 'Common.php') / $divider, 3); + $this->assertSame($size, $file->getSizeByUnitBinary($unit)); + } + + public function testGetSizeBinaryBytes(): void + { + $file = new File(SYSTEMPATH . 'Common.php'); + $size = filesize(SYSTEMPATH . 'Common.php'); + $this->assertSame($size, $file->getSizeByUnitBinary(FileSizeUnit::B)); + } + + /** + * @dataProvider provideGetSizeData + */ + public function testGetSizeMetric(FileSizeUnit $unit): void + { + $divider = pow(1000, $unit->value); + $file = new File(SYSTEMPATH . 'Common.php'); + $size = number_format(filesize(SYSTEMPATH . 'Common.php') / $divider, 3); + $this->assertSame($size, $file->getSizeByUnitMetric($unit)); + } + + public function testGetSizeMetricBytes(): void + { + $file = new File(SYSTEMPATH . 'Common.php'); + $size = filesize(SYSTEMPATH . 'Common.php'); + $this->assertSame($size, $file->getSizeByUnitMetric(FileSizeUnit::B)); + } + public function testThrowsExceptionIfNotAFile(): void { $this->expectException(FileNotFoundException::class); @@ -135,4 +171,22 @@ public function testGetDestination(): void unlink(SYSTEMPATH . 'Common_Copy.php'); unlink(SYSTEMPATH . 'Common_Copy_5.php'); } + + public static function provideGetSizeData() + { + return [ + 'returns KB binary' => [ + FileSizeUnit::KB + ], + 'returns MB binary' => [ + FileSizeUnit::KB + ], + 'returns GB binary' => [ + FileSizeUnit::KB + ], + 'returns TB binary' => [ + FileSizeUnit::KB + ], + ]; + } } diff --git a/user_guide_src/source/changelogs/v4.6.0.rst b/user_guide_src/source/changelogs/v4.6.0.rst index d3dc4529d512..c1d2d59b36a2 100644 --- a/user_guide_src/source/changelogs/v4.6.0.rst +++ b/user_guide_src/source/changelogs/v4.6.0.rst @@ -277,6 +277,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 ``getSizeByUnitBinary`` or ``getSizeByUnitMetric`` instead. ********** Bugs Fixed diff --git a/user_guide_src/source/libraries/files.rst b/user_guide_src/source/libraries/files.rst index 1622c3345c51..c171b5b047a1 100644 --- a/user_guide_src/source/libraries/files.rst +++ b/user_guide_src/source/libraries/files.rst @@ -56,14 +56,40 @@ 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. +getSizeByUnitBinary() +=============== + +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: 2- + +A ``RuntimeException`` will be thrown if the file does not exist or an error occurs. + +getSizeByUnitMetric() +=============== + +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: 2- + +A ``RuntimeException`` will be thrown if the file does not exist or an error occurs. + getMimeType() ============= diff --git a/user_guide_src/source/libraries/files/017.php b/user_guide_src/source/libraries/files/017.php new file mode 100644 index 000000000000..f3cd9450af9c --- /dev/null +++ b/user_guide_src/source/libraries/files/017.php @@ -0,0 +1,5 @@ +getSizeByUnitBinary(); // 256901 +$kibibytes = $file->getSizeByUnitBinary(FileSizeUnit::KB); // 250.880 +$mebibytes = $file->getSizeByUnitBinary(FileSizeUnit::MB); // 0.245 diff --git a/user_guide_src/source/libraries/files/018.php b/user_guide_src/source/libraries/files/018.php new file mode 100644 index 000000000000..89138f8dbc04 --- /dev/null +++ b/user_guide_src/source/libraries/files/018.php @@ -0,0 +1,5 @@ +getSizeByUnitMetric(); // 256901 +$kilobytes = $file->getSizeByUnitMetric(FileSizeUnit::KB); // 256.901 +$megabytes = $file->getSizeByUnitMetric(FileSizeUnit::MB); // 0.256