diff --git a/.phive/phars.xml b/.phive/phars.xml
index 36149ce..d3c0604 100644
--- a/.phive/phars.xml
+++ b/.phive/phars.xml
@@ -1,9 +1,9 @@
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/src/Check/Encoding.php b/src/Check/Encoding.php
index 08cb9df..b690c04 100644
--- a/src/Check/Encoding.php
+++ b/src/Check/Encoding.php
@@ -114,7 +114,7 @@ class Encoding
(($char != $r_char && (!self::$mb_error_char ||
in_array(self::$mb_error_char, ['none', 'long', 'entity']))) ||
($char != $r_char && $r_char == self::$mb_error_char && self::$mb_error_char)) &&
- ord($char) != 194
+ ord($char[0]) != 194
) {
$failed[] = $char;
}
diff --git a/src/Convert/Byte.php b/src/Convert/Byte.php
index 22e9cbf..a9ddbd9 100644
--- a/src/Convert/Byte.php
+++ b/src/Convert/Byte.php
@@ -14,6 +14,7 @@ class Byte
public const BYTE_FORMAT_NOSPACE = 1;
public const BYTE_FORMAT_ADJUST = 2;
public const BYTE_FORMAT_SI = 4;
+ public const RETURN_AS_STRING = 8;
/**
* This function replaces the old byteStringFormat
@@ -119,7 +120,9 @@ class Byte
* @param int $flags bitwise flag with use space turned on
* BYTE_FORMAT_SI: use 1000 instead of 1024
* @return string|int|float converted value or original value
- * @throws \InvalidArgumentException 1: no valid flag set
+ * @throws \InvalidArgumentException no valid flag set
+ * @throws \LengthException number too large to convert to int
+ * @throws \RuntimeException BCMath extension not loaded if flag is set to string
*/
public static function stringByteFormat(string|int|float $number, int $flags = 0): string|int|float
{
@@ -129,7 +132,12 @@ class Byte
} else {
$si = false;
}
- if ($flags != 0 && $flags != 4) {
+ if ($flags & self::RETURN_AS_STRING) {
+ $return_as_string = true;
+ } else {
+ $return_as_string = false;
+ }
+ if ($flags != 0 && $flags != 4 && $flags != 8 && $flags != 12) {
throw new \InvalidArgumentException("Invalid flags parameter: $flags", 1);
}
// matches in regex
@@ -142,6 +150,10 @@ class Byte
strtolower((string)$number),
$matches
);
+ $number_negative = false;
+ if (!empty($matches[1])) {
+ $number_negative = true;
+ }
if (isset($matches[2]) && isset($matches[3])) {
// remove all non valid characters from the number
$number = preg_replace('/[^0-9\.]/', '', $matches[2]);
@@ -152,12 +164,48 @@ class Byte
if ($unit) {
$number = $number * pow($si ? 1000 : 1024, stripos($valid_units_, $unit[0]) ?: 0);
}
+ // if the number is too large, we cannot convert to int directly
+ if ($number <= PHP_INT_MIN || $number >= PHP_INT_MAX) {
+ // if we do not want to convert to string
+ if (!$return_as_string) {
+ throw new \LengthException(
+ 'Number too large be converted to int: ' . (string)$number
+ );
+ }
+ // for string, check if bcmath is loaded, if not this will not work
+ if (!extension_loaded('bcmath')) {
+ throw new \RuntimeException(
+ 'Number too large be converted to int and BCMath extension not loaded: ' . (string)$number
+ );
+ }
+ }
+ // string return
+ if ($return_as_string) {
+ // return as string to avoid overflow
+ // $number = (string)round($number);
+ $number = bcmul(number_format(
+ $number,
+ 12,
+ '.',
+ ''
+ ), "1");
+ if ($number_negative) {
+ $number = '-' . $number;
+ }
+ return $number;
+ }
// convert to INT to avoid +E output
$number = (int)round($number);
// if negative input, keep nnegative
- if (!empty($matches[1])) {
+ if ($number_negative) {
$number *= -1;
}
+ // check if number is negative but should be, this is Lenght overflow
+ if (!$number_negative && $number < 0) {
+ throw new \LengthException(
+ 'Number too large be converted to int: ' . (string)$number
+ );
+ }
}
// if not matching return as is
return $number;
diff --git a/src/Convert/Math.php b/src/Convert/Math.php
index 368c485..6aba6f4 100644
--- a/src/Convert/Math.php
+++ b/src/Convert/Math.php
@@ -62,10 +62,15 @@ class Math
*
* @param float $number Number to cubic root
* @return float Calculated value
+ * @throws \InvalidArgumentException if $number is negative
*/
public static function cbrt(float|int $number): float
{
- return pow((float)$number, 1.0 / 3);
+ $value = pow((float)$number, 1.0 / 3);
+ if (is_nan($value)) {
+ throw new \InvalidArgumentException('cube root from this number is not supported: ' . $number);
+ }
+ return $value;
}
/**
diff --git a/src/Logging/ErrorMessage.php b/src/Logging/ErrorMessage.php
index bf99f97..153faf2 100644
--- a/src/Logging/ErrorMessage.php
+++ b/src/Logging/ErrorMessage.php
@@ -291,7 +291,7 @@ class ErrorMessage
*/
public function getLastErrorMsg(): array
{
- return $this->error_str[array_key_last($this->error_str)] ?? [
+ return $this->error_str[array_key_last($this->error_str) ?? -1] ?? [
'level' => '',
'str' => '',
'id' => '',
diff --git a/src/Output/Image.php b/src/Output/Image.php
index aa44960..94d7f18 100644
--- a/src/Output/Image.php
+++ b/src/Output/Image.php
@@ -365,9 +365,6 @@ class Image
imagepng($thumb, $thumbnail_write_path . $thumbnail);
break;
}
- // free up resources (in case we are called in a loop)
- imagedestroy($source);
- imagedestroy($thumb);
} else {
throw new \RuntimeException(
'Invalid source image file. Only JPEG/PNG are allowed: ' . $filename,
@@ -543,8 +540,6 @@ class Image
imagepng($img, $filename);
break;
}
- // clean up image if we have an image
- imagedestroy($img);
}
}
diff --git a/src/UrlRequests/Curl.php b/src/UrlRequests/Curl.php
index 40b306f..1af6318 100644
--- a/src/UrlRequests/Curl.php
+++ b/src/UrlRequests/Curl.php
@@ -614,8 +614,6 @@ class Curl implements Interface\RequestsInterface
// print "CURLINFO_HEADER_OUT:
" . curl_getinfo($handle, CURLINFO_HEADER_OUT) . "
";
// get response code and bail on not authorized
$http_response = $this->handleCurlResponse($handle, $http_result, $options['http_errors']);
- // close handler
- $this->handleCurlClose($handle);
// return response and result
return [
'code' => (string)$http_response,
@@ -838,17 +836,6 @@ class Curl implements Interface\RequestsInterface
);
}
- /**
- * close the current curl handle
- *
- * @param \CurlHandle $handle
- * @return void
- */
- private function handleCurlClose(\CurlHandle $handle): void
- {
- curl_close($handle);
- }
-
// *********************************************************************
// MARK: PUBLIC METHODS
// *********************************************************************
diff --git a/test/phpunit/Convert/CoreLibsConvertByteTest.php b/test/phpunit/Convert/CoreLibsConvertByteTest.php
index 0cd1682..a80b091 100644
--- a/test/phpunit/Convert/CoreLibsConvertByteTest.php
+++ b/test/phpunit/Convert/CoreLibsConvertByteTest.php
@@ -123,47 +123,6 @@ final class CoreLibsConvertByteTest extends TestCase
];
}
- /**
- * Undocumented function
- *
- * @return array
- */
- public function byteStringProvider(): array
- {
- return [
- 'negative number' => [
- 0 => '-117.42 MB',
- 1 => -123123794,
- 2 => -117420000,
- ],
- 'megabyte' => [
- 0 => '242.98 MB',
- 1 => 254782996,
- 2 => 242980000
- ],
- 'megabyte si' => [
- 0 => '254.78 MiB',
- 1 => 267156193,
- 2 => 254780000
- ],
- 'petabyte' => [
- 0 => '1 EiB',
- 1 => 1152921504606846976,
- 2 => 1000000000000000000,
- ],
- 'max int' => [
- 0 => '8 EB',
- 1 => -9223372036854775807 - 1,
- 2 => 8000000000000000000,
- ],
- 'exabyte, overflow' => [
- 0 => '867.36EB',
- 1 => 3873816255479021568,
- 2 => 363028535651074048,
- ]
- ];
- }
-
/**
* Undocumented function
*
@@ -180,7 +139,7 @@ final class CoreLibsConvertByteTest extends TestCase
* @return void
*/
public function testHumanReadableByteFormat(
- $input,
+ string|int|float $input,
string $expected,
string $expected_si,
string $expected_no_space,
@@ -217,6 +176,73 @@ final class CoreLibsConvertByteTest extends TestCase
);
}
+ /**
+ * Undocumented function
+ *
+ * @return array
+ */
+ public function byteStringProvider(): array
+ {
+ return [
+ 'negative number' => [
+ 0 => '-117.42 MB',
+ 1 => -123123794,
+ 2 => -117420000,
+ 3 => "-123123793",
+ 4 => "-117420000",
+ 5 => null,
+ ],
+ 'megabyte' => [
+ 0 => '242.98 MB',
+ 1 => 254782996,
+ 2 => 242980000,
+ 3 => "254782996",
+ 4 => "242980000",
+ 5 => null,
+ ],
+ 'megabyte si' => [
+ 0 => '254.78 MiB',
+ 1 => 267156193,
+ 2 => 254780000,
+ 3 => "267156193",
+ 4 => "254780000",
+ 5 => null,
+ ],
+ 'petabyte' => [
+ 0 => '1 EiB',
+ 1 => 1152921504606846976,
+ 2 => 1000000000000000000,
+ 3 => "1152921504606846976",
+ 4 => "1000000000000000000",
+ 5 => null,
+ ],
+ 'max int' => [
+ 0 => '8 EB',
+ 1 => 0,
+ 2 => 0,
+ 3 => "9223372036854775808",
+ 4 => "8000000000000000000",
+ 5 => \LengthException::class,
+ ],
+ 'exabyte, overflow' => [
+ 0 => '867.36EB',
+ 1 => 0,
+ 2 => 0,
+ 3 => "999997996235794808832",
+ 4 => "867360000000000000000",
+ 5 => \LengthException::class,
+ ],
+ 'huge exabyte, overflow' => [
+ 0 => '1000EB',
+ 1 => 0,
+ 2 => 0,
+ 3 => "1152921504606846976000",
+ 4 => "1000000000000000000000",
+ 5 => \LengthException::class,
+ ],
+ ];
+ }
+
/**
* Undocumented function
*
@@ -227,10 +253,22 @@ final class CoreLibsConvertByteTest extends TestCase
* @param string|int|float $input
* @param string|int|float $expected
* @param string|int|float $expected_si
+ * @param string|int|float $expected_string
+ * @param string|int|float $expected_string_si
+ * @param ?string $exception
* @return void
*/
- public function testStringByteFormat($input, $expected, $expected_si): void
- {
+ public function testStringByteFormat(
+ string|int|float $input,
+ string|int|float $expected,
+ string|int|float $expected_si,
+ string|int|float $expected_string,
+ string|int|float $expected_string_si,
+ ?string $exception
+ ): void {
+ if ($exception !== null) {
+ $this->expectException($exception);
+ }
$this->assertEquals(
$expected,
\CoreLibs\Convert\Byte::stringByteFormat($input)
@@ -239,6 +277,17 @@ final class CoreLibsConvertByteTest extends TestCase
$expected_si,
\CoreLibs\Convert\Byte::stringByteFormat($input, \CoreLibs\Convert\Byte::BYTE_FORMAT_SI)
);
+ $this->assertEquals(
+ $expected_string,
+ \CoreLibs\Convert\Byte::stringByteFormat($input, \CoreLibs\Convert\Byte::RETURN_AS_STRING)
+ );
+ $this->assertEquals(
+ $expected_string_si,
+ \CoreLibs\Convert\Byte::stringByteFormat(
+ $input,
+ \CoreLibs\Convert\Byte::BYTE_FORMAT_SI | \CoreLibs\Convert\Byte::RETURN_AS_STRING
+ )
+ );
}
/**
diff --git a/test/phpunit/Convert/CoreLibsConvertMathTest.php b/test/phpunit/Convert/CoreLibsConvertMathTest.php
index 5df06aa..c3aa145 100644
--- a/test/phpunit/Convert/CoreLibsConvertMathTest.php
+++ b/test/phpunit/Convert/CoreLibsConvertMathTest.php
@@ -122,9 +122,9 @@ final class CoreLibsConvertMathTest extends TestCase
public function providerCbrt(): array
{
return [
- 'cube root of 2' => [2, 1.25992, 5],
- 'cube root of 3' => [3, 1.44225, 5],
- 'cube root of -1' => [-1, 'NAN', 0],
+ 'cube root of 2' => [2, 1.25992, 5, null],
+ 'cube root of 3' => [3, 1.44225, 5, null],
+ 'cube root of -1' => [-1, 'NAN', 0, \InvalidArgumentException::class],
];
}
@@ -138,10 +138,14 @@ final class CoreLibsConvertMathTest extends TestCase
* @param float|int $number
* @param float $expected
* @param int $round_to
+ * @param ?string $exception
* @return void
*/
- public function testCbrt(float|int $number, float|string $expected, int $round_to): void
+ public function testCbrt(float|int $number, float|string $expected, int $round_to, ?string $exception): void
{
+ if ($exception !== null) {
+ $this->expectException($exception);
+ }
$this->assertEquals(
$expected,
round(\CoreLibs\Convert\Math::cbrt($number), $round_to)
diff --git a/test/phpunit/UrlRequests/CoreLibsUrlRequestsCurlTest.php b/test/phpunit/UrlRequests/CoreLibsUrlRequestsCurlTest.php
index e5a2202..75c7a14 100644
--- a/test/phpunit/UrlRequests/CoreLibsUrlRequestsCurlTest.php
+++ b/test/phpunit/UrlRequests/CoreLibsUrlRequestsCurlTest.php
@@ -59,8 +59,6 @@ final class CoreLibsUrlRequestsCurlTest extends TestCase
continue;
}
$this->url_basic = $url;
- // split out the last / part for url set test
- curl_close($handle);
// print "Open: $url\n";
break;
}
@@ -969,76 +967,77 @@ final class CoreLibsUrlRequestsCurlTest extends TestCase
"query" => ["foo-get" => "bar"]
]);
$this->assertEquals("200", $response["code"], "multi call: get response code not matching");
- if (PHP_VERSION_ID >= 80400) {
- $this->assertEquals(
- '{"HEADERS":{"HTTP_HOST":"soba.egplusww.jp",'
- . '"HTTP_USER_AGENT":"CoreLibsUrlRequestCurl\/1","HTTP_FIRST_CALL":"get",'
- . '"HTTP_ACCEPT":"*\/*"},"REQUEST_TYPE":"GET","PARAMS":{"foo-get":"bar"},"BODY":null}',
- $response['content'],
- 'multi call: get content not matching'
- );
- } else {
- $this->assertEquals(
- '{"HEADERS":{"HTTP_USER_AGENT":"CoreLibsUrlRequestCurl\/1",'
- . '"HTTP_FIRST_CALL":"get","HTTP_ACCEPT":"*\/*",'
- . '"HTTP_HOST":"soba.egplusww.jp"},'
- . '"REQUEST_TYPE":"GET",'
- . '"PARAMS":{"foo-get":"bar"},"BODY":null}',
- $response['content'],
- 'multi call: get content not matching'
- );
- }
+ $request_expected = json_decode(
+ <<assertEquals(
+ $request_expected,
+ json_decode($response['content'], true),
+ 'multi call: get content not matching'
+ );
// post
$response = $curl->post($this->url_basic, [
"headers" => ["second-call" => "post"],
"body" => ["foo-post" => "baz"]
]);
$this->assertEquals("200", $response["code"], "multi call: post response code not matching");
- if (PHP_VERSION_ID >= 80400) {
- $this->assertEquals(
- '{"HEADERS":{"HTTP_HOST":"soba.egplusww.jp",'
- . '"HTTP_USER_AGENT":"CoreLibsUrlRequestCurl\/1",'
- . '"HTTP_SECOND_CALL":"post","HTTP_ACCEPT":"*\/*"},'
- . '"REQUEST_TYPE":"POST","PARAMS":[],"BODY":{"foo-post":"baz"}}',
- $response['content'],
- 'multi call: post content not matching'
- );
- } else {
- $this->assertEquals(
- '{"HEADERS":{"HTTP_USER_AGENT":"CoreLibsUrlRequestCurl\/1",'
- . '"HTTP_SECOND_CALL":"post","HTTP_ACCEPT":"*\/*",'
- . '"HTTP_HOST":"soba.egplusww.jp"},'
- . '"REQUEST_TYPE":"POST",'
- . '"PARAMS":[],"BODY":{"foo-post":"baz"}}',
- $response['content'],
- 'multi call: post content not matching'
- );
- }
+ $request_expected = json_decode(
+ <<assertEquals(
+ $request_expected,
+ json_decode($response['content'], true),
+ 'multi call: post content not matching'
+ );
// delete
$response = $curl->delete($this->url_basic, [
"headers" => ["third-call" => "delete"],
]);
$this->assertEquals("200", $response["code"], "multi call: delete response code not matching");
- if (PHP_VERSION_ID >= 80400) {
- $this->assertEquals(
- '{"HEADERS":{"HTTP_HOST":"soba.egplusww.jp",'
- . '"HTTP_USER_AGENT":"CoreLibsUrlRequestCurl\/1",'
- . '"HTTP_THIRD_CALL":"delete","HTTP_ACCEPT":"*\/*"},'
- . '"REQUEST_TYPE":"DELETE","PARAMS":[],"BODY":[]}',
- $response['content'],
- 'multi call: delete content not matching'
- );
- } else {
- $this->assertEquals(
- '{"HEADERS":{"HTTP_USER_AGENT":"CoreLibsUrlRequestCurl\/1",'
- . '"HTTP_THIRD_CALL":"delete","HTTP_ACCEPT":"*\/*",'
- . '"HTTP_HOST":"soba.egplusww.jp"},'
- . '"REQUEST_TYPE":"DELETE",'
- . '"PARAMS":[],"BODY":[]}',
- $response['content'],
- 'multi call: delete content not matching'
- );
- }
+ $request_expected = json_decode(
+ <<assertEquals(
+ $request_expected,
+ json_decode($response['content'], true),
+ 'multi call: delete content not matching'
+ );
}
// MARK: auth header set via config