From a7b0c70b296fbb1b7e7aaf1c6708f6dcce79ca3b Mon Sep 17 00:00:00 2001
From: Hafiz Rahman <hfzrhmn@gmail.com>
Date: Thu, 5 Dec 2024 13:24:19 +0700
Subject: [PATCH 1/8] Add string extension function to convert a String
 containing number to readable file size.

---
 .../android/extensions/StringExt.kt           | 30 +++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/extensions/StringExt.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/extensions/StringExt.kt
index 66d7d747612..447efd97e8a 100644
--- a/WooCommerce/src/main/kotlin/com/woocommerce/android/extensions/StringExt.kt
+++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/extensions/StringExt.kt
@@ -1,7 +1,12 @@
 package com.woocommerce.android.extensions
 
 import org.apache.commons.text.StringEscapeUtils
+import java.text.DecimalFormat
 import java.util.Locale
+import kotlin.math.log10
+import kotlin.math.pow
+
+const val BYTES_IN_KILOBYTE = 1024.0
 
 /**
  * Checks if a given string is a Float
@@ -100,3 +105,28 @@ fun String.toCamelCase(delimiter: String = " "): String {
 fun String.capitalize(locale: Locale = Locale.getDefault()) = replaceFirstChar {
     if (it.isLowerCase()) it.titlecase(locale) else it.toString()
 }
+
+/**
+ * Converts a numeric string representing bytes into a human-readable file size string.
+ *
+ * Source: https://stackoverflow.com/a/5599842
+ *
+ * Examples:
+ * "1024".readableFileSize() -> "1 kB"
+ * "1500000".readableFileSize() -> "1.4 MB"
+ * "0".readableFileSize() -> "0"
+ * Invalid input returns "0"
+ *
+ *
+ * @return Formatted string with size and unit (e.g., "1.5 GB")
+ */
+fun String.readableFileSize(): String {
+    val size = this.toLongOrNull()
+    if (size == null || size <= 0) return "0"
+
+    val units = arrayOf("B", "kB", "MB", "GB", "TB", "PB", "EB")
+    val digitGroups = (log10(size.toDouble()) / log10(BYTES_IN_KILOBYTE)).toInt()
+
+    return DecimalFormat("#,##0.#")
+        .format(size / BYTES_IN_KILOBYTE.pow(digitGroups.toDouble())) + " " + units[digitGroups]
+}

From 58c3a29c5c6aefbad83c5eafe2be53ed5ae32f59 Mon Sep 17 00:00:00 2001
From: Hafiz Rahman <hfzrhmn@gmail.com>
Date: Thu, 5 Dec 2024 13:26:02 +0700
Subject: [PATCH 2/8] Add unit tests

---
 .../android/extensions/StringExtTest.kt       | 57 +++++++++++++++++++
 1 file changed, 57 insertions(+)
 create mode 100644 WooCommerce/src/test/kotlin/com/woocommerce/android/extensions/StringExtTest.kt

diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/extensions/StringExtTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/extensions/StringExtTest.kt
new file mode 100644
index 00000000000..7b98425c5db
--- /dev/null
+++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/extensions/StringExtTest.kt
@@ -0,0 +1,57 @@
+package com.woocommerce.android.extensions
+
+import org.assertj.core.api.Assertions.assertThat
+import org.junit.Test
+
+class StringExtTest {
+    @Test
+    fun `given string with valid size, when readableFileSize called, then returns formatted size`() {
+        // Given
+        val inputs = mapOf(
+            "1024" to "1 kB",
+            "1500000" to "1.4 MB",
+            "1234567" to "1.2 MB",
+            "1073741824" to "1 GB",
+            "1099511627776" to "1 TB"
+        )
+
+        // When & then
+        inputs.forEach { (input, expected) ->
+            assertThat(input.readableFileSize()).isEqualTo(expected)
+        }
+    }
+
+    @Test
+    fun `given zero or negative size, when readableFileSize called, then returns zero`() {
+        // Given
+        val inputs = listOf("0", "-1024", "-1")
+
+        // When & then
+        inputs.forEach { input ->
+            assertThat(input.readableFileSize()).isEqualTo("0")
+        }
+    }
+
+    @Test
+    fun `given invalid number string, when readableFileSize called, then returns zero`() {
+        // Given
+        val inputs = listOf("", "abc", "12.34", "1,000")
+
+        // When & then
+        inputs.forEach { input ->
+            assertThat(input.readableFileSize()).isEqualTo("0")
+        }
+    }
+
+    @Test
+    fun `given very large number, when readableFileSize called, then returns correct unit`() {
+        // Given
+        val size = "1" + "0".repeat(18) // 1 quintillion bytes
+
+        // When
+        val result = size.readableFileSize()
+
+        // Then
+        assertThat(result).isEqualTo("888.2 PB")
+    }
+}

From 0b5a08d1ebafd85d0a36cbd1ac7825cc762c8d3a Mon Sep 17 00:00:00 2001
From: Hafiz Rahman <hfzrhmn@gmail.com>
Date: Thu, 5 Dec 2024 13:26:27 +0700
Subject: [PATCH 3/8] Replace usage of commons.io function with the newly added
 function

---
 .../com/woocommerce/android/extensions/WCSSRModelExt.kt    | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/extensions/WCSSRModelExt.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/extensions/WCSSRModelExt.kt
index b226692b3fe..45e47815eb4 100644
--- a/WooCommerce/src/main/kotlin/com/woocommerce/android/extensions/WCSSRModelExt.kt
+++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/extensions/WCSSRModelExt.kt
@@ -4,7 +4,6 @@ package com.woocommerce.android.extensions
 
 import androidx.core.text.HtmlCompat
 import com.woocommerce.android.util.WooLog
-import org.apache.commons.io.FileUtils.byteCountToDisplaySize
 import org.json.JSONArray
 import org.json.JSONException
 import org.json.JSONObject
@@ -110,7 +109,7 @@ private fun formatEnvironmentData(data: JSONObject): String {
 
     val memoryLimit = data.optString("wp_memory_limit", MISSING_VALUE)
     if (memoryLimit != MISSING_VALUE) {
-        sb.append("WP Memory Limit: ${byteCountToDisplaySize(memoryLimit.toLong())}\n")
+        sb.append("WP Memory Limit: ${memoryLimit.readableFileSize()}\n")
     }
 
     sb.append("WP Debug Mode: ${checkIfTrue(data.optBoolean("wp_debug_mode", false))}\n")
@@ -123,7 +122,7 @@ private fun formatEnvironmentData(data: JSONObject): String {
 
     val postMaxSize = data.optString("php_post_max_size", MISSING_VALUE)
     if (postMaxSize != MISSING_VALUE) {
-        sb.append("PHP Post Max Size: ${byteCountToDisplaySize(postMaxSize.toLong())}\n")
+        sb.append("WP Memory Limit: ${postMaxSize.readableFileSize()}\n")
     }
 
     sb.append("PHP Time Limit: ${data.optString("php_max_execution_time", MISSING_VALUE)} s\n")
@@ -134,7 +133,7 @@ private fun formatEnvironmentData(data: JSONObject): String {
 
     val maxUploadSize = data.optString("max_upload_size", MISSING_VALUE)
     if (maxUploadSize != MISSING_VALUE) {
-        sb.append("PHP Post Max Size: ${byteCountToDisplaySize(maxUploadSize.toLong())}\n")
+        sb.append("WP Memory Limit: ${maxUploadSize.readableFileSize()}\n")
     }
 
     sb.append("Default Timezone: ${data.optString("default_timezone", MISSING_VALUE)}\n")

From bc230540ad4c79a0c3b2cda21e12ab008f1bc656 Mon Sep 17 00:00:00 2001
From: Hafiz Rahman <hfzrhmn@gmail.com>
Date: Thu, 5 Dec 2024 13:26:52 +0700
Subject: [PATCH 4/8] Remove dependency for commons-io now that it's not used
 anymore.

---
 WooCommerce/build.gradle  | 1 -
 gradle/libs.versions.toml | 2 --
 2 files changed, 3 deletions(-)

diff --git a/WooCommerce/build.gradle b/WooCommerce/build.gradle
index 8959fc8e102..10af4a18dec 100644
--- a/WooCommerce/build.gradle
+++ b/WooCommerce/build.gradle
@@ -442,7 +442,6 @@ dependencies {
     testImplementation(libs.cashapp.turbine)
 
     implementation(libs.apache.commons.text)
-    implementation(libs.commons.io)
 
     implementation(libs.tinder.statemachine)
 
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 5db15828723..0725c1c9b5f 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -42,7 +42,6 @@ bumptech-glide = '4.16.0'
 cashapp-turbine = '1.0.0'
 coil = '2.1.0'
 commons-fileupload = '1.5'
-commons-io = '2.11.0'
 dependency-analysis = '1.28.0'
 detekt = '1.23.5'
 facebook-flipper = '0.176.1'
@@ -172,7 +171,6 @@ cashapp-turbine = { group = "app.cash.turbine", name = "turbine", version.ref =
 coil-compose = { group = "io.coil-kt", name = "coil-compose", version.ref = "coil" }
 coil-svg = { group = "io.coil-kt", name = "coil-svg", version.ref = "coil" }
 commons-fileupload = { group = "commons-fileupload", name = "commons-fileupload", version.ref = "commons-fileupload" }
-commons-io = { group = "commons-io", name = "commons-io", version.ref = "commons-io" }
 detekt-formatting = { group = "io.gitlab.arturbosch.detekt", name = "detekt-formatting", version.ref = "detekt" }
 facebook-flipper-main = { group = "com.facebook.flipper", name = "flipper", version.ref = "facebook-flipper" }
 facebook-flipper-network-plugin = { group = "com.facebook.flipper", name = "flipper-network-plugin", version.ref = "facebook-flipper" }

From d130bf4d1256bb0353dafb7846ce0058a54e2772 Mon Sep 17 00:00:00 2001
From: Hafiz Rahman <hfzrhmn@gmail.com>
Date: Thu, 5 Dec 2024 13:33:11 +0700
Subject: [PATCH 5/8] Fix labels

---
 .../com/woocommerce/android/extensions/WCSSRModelExt.kt       | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/extensions/WCSSRModelExt.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/extensions/WCSSRModelExt.kt
index 45e47815eb4..580f24a7392 100644
--- a/WooCommerce/src/main/kotlin/com/woocommerce/android/extensions/WCSSRModelExt.kt
+++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/extensions/WCSSRModelExt.kt
@@ -122,7 +122,7 @@ private fun formatEnvironmentData(data: JSONObject): String {
 
     val postMaxSize = data.optString("php_post_max_size", MISSING_VALUE)
     if (postMaxSize != MISSING_VALUE) {
-        sb.append("WP Memory Limit: ${postMaxSize.readableFileSize()}\n")
+        sb.append("PHP Post Max Size: ${postMaxSize.readableFileSize()}\n")
     }
 
     sb.append("PHP Time Limit: ${data.optString("php_max_execution_time", MISSING_VALUE)} s\n")
@@ -133,7 +133,7 @@ private fun formatEnvironmentData(data: JSONObject): String {
 
     val maxUploadSize = data.optString("max_upload_size", MISSING_VALUE)
     if (maxUploadSize != MISSING_VALUE) {
-        sb.append("WP Memory Limit: ${maxUploadSize.readableFileSize()}\n")
+        sb.append("Max Upload Size: ${maxUploadSize.readableFileSize()}\n")
     }
 
     sb.append("Default Timezone: ${data.optString("default_timezone", MISSING_VALUE)}\n")

From 369bcf38b81edbed1cc020ef0efe99aa5a1d65a4 Mon Sep 17 00:00:00 2001
From: Hafiz Rahman <hfzrhmn@gmail.com>
Date: Thu, 5 Dec 2024 13:34:38 +0700
Subject: [PATCH 6/8] Quick code cleanup

---
 .../kotlin/com/woocommerce/android/extensions/WCSSRModelExt.kt  | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/extensions/WCSSRModelExt.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/extensions/WCSSRModelExt.kt
index 580f24a7392..29bee6443af 100644
--- a/WooCommerce/src/main/kotlin/com/woocommerce/android/extensions/WCSSRModelExt.kt
+++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/extensions/WCSSRModelExt.kt
@@ -37,7 +37,7 @@ fun WCSSRModel.formatResult(): String {
     sb.append(HEADING_SSR)
 
     // Environment
-    environment?.let { it ->
+    environment?.let {
         try {
             sb.append(formatEnvironmentData(JSONObject(it)))
         } catch (e: JSONException) {

From d6a4cd1fa2422928195d0d7fa79623a05cb32efc Mon Sep 17 00:00:00 2001
From: Hafiz Rahman <hfzrhmn@gmail.com>
Date: Thu, 5 Dec 2024 13:40:54 +0700
Subject: [PATCH 7/8] Update release notes

---
 RELEASE-NOTES.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index 2343bb3ddda..bf26f1e2931 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -9,6 +9,7 @@
 - [Internal] Refactored IPP Payment flow to allow customizing payment collection UI in POS [https://github.com/woocommerce/woocommerce-android/pull/13014]
 - [*] Blaze Campaign Intro screen now offers creating a new product if the site has no products yet [https://github.com/woocommerce/woocommerce-android/pull/13001]
 - [*] When entering a wrong WordPress.com account for login, retrying will bring the step back to the email input screen [https://github.com/woocommerce/woocommerce-android/pull/13024]
+- [Internal] Replaces a function in WCSSRExt that then removes the need for commons-io dependency. [https://github.com/woocommerce/woocommerce-android/pull/13073]
 
 
 -----

From c616faf6ab1b020567aff9e77393b6e6e2f386f9 Mon Sep 17 00:00:00 2001
From: Hafiz Rahman <hfzrhmn@gmail.com>
Date: Wed, 11 Dec 2024 18:31:09 +0700
Subject: [PATCH 8/8] Remove double line break.

---
 .../main/kotlin/com/woocommerce/android/extensions/StringExt.kt  | 1 -
 1 file changed, 1 deletion(-)

diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/extensions/StringExt.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/extensions/StringExt.kt
index 447efd97e8a..ac493d8cb62 100644
--- a/WooCommerce/src/main/kotlin/com/woocommerce/android/extensions/StringExt.kt
+++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/extensions/StringExt.kt
@@ -117,7 +117,6 @@ fun String.capitalize(locale: Locale = Locale.getDefault()) = replaceFirstChar {
  * "0".readableFileSize() -> "0"
  * Invalid input returns "0"
  *
- *
  * @return Formatted string with size and unit (e.g., "1.5 GB")
  */
 fun String.readableFileSize(): String {