Skip to content

Commit 7e9fa17

Browse files
committed
Add additional coercion methods
1 parent a63c1bc commit 7e9fa17

File tree

4 files changed

+322
-117
lines changed

4 files changed

+322
-117
lines changed

README.md

+60
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,30 @@ Returns true if `$value` is one of the following:
109109

110110
For any other values it returns false.
111111

112+
### Coerceable::stringToBool
113+
114+
Specifically tests a string if it can be coerced to a boolean. `$value` must be '0' or '1'.
115+
116+
### Coerceable::intToBool
117+
118+
Specifically tests an integer if it can be coerced to a boolean. `$value` must be 0 or 1.
119+
120+
### Coerceable::floatToBool
121+
122+
Specifically tests a float if it can be coerced to a boolean. `$value` must be 0 or 1.
123+
124+
### Coerceable::floatToInt
125+
126+
Specifically tests a float if it can be coerced to an integer. `$value` must not have a fractional part.
127+
128+
### Coerceable::stringToInt
129+
130+
Specifically tests a string if it can be coerced to an integer. `$value` must be a numeric string and not have a fractional part.
131+
132+
### Coerceable::stringToFloat
133+
134+
Specifically tests a string if it can be coerced to a float. `$value` must be a numeric string.
135+
112136
Coerce a value
113137
--------------
114138

@@ -130,6 +154,42 @@ Returns a float if the given value is coerceable, see [Coerceable::toFloat for v
130154

131155
Returns a string if the given value is coerceable, see [Coerceable::toString for valid values](#coerceabletoint), or a TypeError if the value is not coerceable.
132156

157+
### Coerce::stringToBool
158+
159+
Returns a boolean if the given string is coerceable, see [Coerceable::stringToBool for valid values](#coerceablestringtobool), or a TypeError if the value is not coerceable.
160+
161+
### Coerce::intToBool
162+
163+
Returns a boolean if the given int is coerceable, see [Coerceable::intToBool for valid values](#coerceableinttobool), or a TypeError if the value is not coerceable.
164+
165+
### Coerce::floatToBool
166+
167+
Returns a boolean if the given float is coerceable, see [Coerceable::floatToBool for valid values](#coerceablefloattobool), or a TypeError if the value is not coerceable.
168+
169+
### Coerce::floatToInt
170+
171+
Returns an integer if the given float is coerceable, see [Coerceable::floatToInt for valid values](#coerceablefloattoint), or a TypeError if the value is not coerceable.
172+
173+
### Coerce::stringToInt
174+
175+
Returns an integer if the given string is coerceable, see [Coerceable::stringToInt for valid values](#coerceablestringtoint), or a TypeError if the value is not coerceable.
176+
177+
### Coerce::stringToFloat
178+
179+
Returns a float if the given string is coerceable, see [Coerceable::stringToFloat for valid values](#coerceablestringtofloat), or a TypeError if the value is not coerceable.
180+
181+
### Coerce::boolToString
182+
183+
Coerces a boolean to a string, returning either '0' or '1'.
184+
185+
### Coerce::intToString
186+
187+
Coerces an integer to a string, returning a numeric string.
188+
189+
### Coerce::floatToString
190+
191+
Coerces a float to a string, returning a numeric string.
192+
133193
Enforce a type for a value
134194
--------------------------
135195

src/Coerce.php

+124-61
Original file line numberDiff line numberDiff line change
@@ -18,33 +18,16 @@ public static function toBool(mixed $value, bool $allowEmptyString = false, bool
1818
return $value;
1919
}
2020

21-
if (
22-
$value === '0'
23-
|| $value === '1'
24-
|| (
25-
$allowEmptyString === true
26-
&& $value === ''
27-
)
28-
) {
29-
return $value === '1';
21+
if (\is_string($value)) {
22+
return self::stringToBool($value, allowEmptyString: $allowEmptyString);
3023
}
3124

32-
if (
33-
$value === 0
34-
|| $value === 1
35-
) {
36-
return $value === 1;
25+
if (\is_int($value)) {
26+
return self::intToBool($value);
3727
}
3828

39-
if (
40-
$allowFloat === true
41-
&& \is_float($value)
42-
&& (
43-
\abs(1.0 - $value) < PHP_FLOAT_EPSILON
44-
|| \abs(0.0 - $value) < PHP_FLOAT_EPSILON
45-
)
46-
) {
47-
return \abs(1.0 - $value) < PHP_FLOAT_EPSILON;
29+
if (\is_float($value) && $allowFloat === true) {
30+
return self::floatToBool($value);
4831
}
4932

5033
throw new TypeError('Only 0 and 1' . ( $allowEmptyString ? ' and \'\'' : '' ) . ' are alternative coerceable values for a boolean, given value: ' . Debug::sanitizeData($value));
@@ -60,18 +43,16 @@ public static function toInt(mixed $value, bool $allowBool = false): int
6043
return $value;
6144
}
6245

63-
if (
64-
$allowBool === true
65-
&& \is_bool($value)
66-
) {
46+
if (\is_bool($value) && $allowBool === true) {
6747
return $value === true ? 1 : 0;
6848
}
6949

70-
if (
71-
\is_numeric($value)
72-
&& \abs(\floatval($value) - \intval($value)) < PHP_FLOAT_EPSILON
73-
) {
74-
return \intval($value);
50+
if (\is_float($value)) {
51+
return self::floatToInt($value);
52+
}
53+
54+
if (\is_string($value)) {
55+
return self::stringToInt($value);
7556
}
7657

7758
throw new TypeError('Only ' . ( $allowBool ? 'booleans, ' : '' ) . 'numeric strings and floats with no fractional part are alternative coerceable values for an int, given value: ' . Debug::sanitizeData($value));
@@ -83,25 +64,16 @@ public static function toInt(mixed $value, bool $allowBool = false): int
8364
*/
8465
public static function toFloat(mixed $value, bool $allowBool = false): float
8566
{
86-
if (
87-
\is_int($value)
88-
|| \is_float($value)
89-
) {
67+
if (\is_int($value) || \is_float($value)) {
9068
return $value;
9169
}
9270

93-
if (
94-
$allowBool === true
95-
&& \is_bool($value)
96-
) {
71+
if (\is_bool($value) && $allowBool === true) {
9772
return $value === true ? 1 : 0;
9873
}
9974

100-
if (
101-
\is_string($value)
102-
&& \is_numeric($value)
103-
) {
104-
return \floatval($value);
75+
if (\is_string($value)) {
76+
return self::stringToFloat($value);
10577
}
10678

10779
throw new TypeError('Only ' . ( $allowBool ? 'booleans and ' : '' ) . 'numeric strings are alternative coerceable values for a float, given value: ' . Debug::sanitizeData($value));
@@ -113,33 +85,124 @@ public static function toFloat(mixed $value, bool $allowBool = false): float
11385
*/
11486
public static function toString(mixed $value, bool $allowBool = false, bool $allowStringable = false): string
11587
{
116-
if (
117-
\is_string($value)
118-
) {
88+
if (\is_string($value)) {
11989
return $value;
12090
}
12191

122-
if (
123-
\is_int($value)
124-
|| \is_float($value)
125-
) {
92+
if (\is_int($value) || \is_float($value)) {
12693
return \strval($value);
12794
}
12895

129-
if (
130-
$allowBool === true
131-
&& \is_bool($value)
132-
) {
96+
if (\is_bool($value) && $allowBool === true) {
13397
return $value === true ? '1' : '0';
13498
}
13599

136-
if (
137-
$allowStringable === true
138-
&& $value instanceof Stringable
139-
) {
100+
if ($value instanceof Stringable && $allowStringable === true) {
140101
return $value->__toString();
141102
}
142103

143-
throw new TypeError('Only ' . ( $allowBool ? 'booleans, ' : '' ) . '' . ( $allowStringable ? 'Stringable, ' : '' ) . 'integers and floats are alternative coerceable values for a string, given value: ' . Debug::sanitizeData($value));
104+
throw new TypeError('Only ' . ( $allowBool ? 'booleans, ' : '' ) . ( $allowStringable ? 'Stringable, ' : '' ) . 'integers and floats are alternative coerceable values for a string, given value: ' . Debug::sanitizeData($value));
105+
}
106+
107+
/**
108+
* @pure
109+
* @throws TypeError
110+
*/
111+
public static function stringToBool(string $value, bool $allowEmptyString = false): bool
112+
{
113+
if (Coerceable::stringToBool($value, allowEmptyString: $allowEmptyString)) {
114+
return $value === '1';
115+
}
116+
117+
throw new TypeError('Only 0 and 1' . ( $allowEmptyString ? ' and \'\'' : '' ) . ' are alternative coerceable values for a boolean, given value: ' . Debug::sanitizeData($value));
118+
}
119+
120+
/**
121+
* @pure
122+
*/
123+
public static function boolToString(bool $value): string
124+
{
125+
return $value === true ? '1' : '0';
126+
}
127+
128+
/**
129+
* @pure
130+
*/
131+
public static function intToString(int $value): string
132+
{
133+
return \strval($value);
134+
}
135+
136+
/**
137+
* @pure
138+
*/
139+
public static function floatToString(int|float $value): string
140+
{
141+
return \strval($value);
142+
}
143+
144+
/**
145+
* @pure
146+
* @throws TypeError
147+
*/
148+
public static function intToBool(int $value): bool
149+
{
150+
return match($value) {
151+
0 => false,
152+
1 => true,
153+
default => throw new TypeError('Only 0 and 1 can be coerced from an int to a boolean, given value: ' . Debug::sanitizeData($value)),
154+
};
155+
}
156+
157+
/**
158+
* @pure
159+
* @throws TypeError
160+
*/
161+
public static function floatToBool(float $value): bool
162+
{
163+
if (Coerceable::floatToBool($value)) {
164+
return \abs(1.0 - $value) < PHP_FLOAT_EPSILON;
165+
}
166+
167+
throw new TypeError('Only 0 and 1 can be coerced from a float to a boolean, given value: ' . Debug::sanitizeData($value));
168+
}
169+
170+
/**
171+
* @pure
172+
* @throws TypeError
173+
*/
174+
public static function floatToInt(float $value): int
175+
{
176+
if (Coerceable::floatToInt($value)) {
177+
return \intval($value);
178+
}
179+
180+
throw new TypeError('Only numbers with no fractional part can be coerced from a float to an int, given value: ' . Debug::sanitizeData($value));
181+
}
182+
183+
/**
184+
* @pure
185+
* @throws TypeError
186+
*/
187+
public static function stringToInt(string $value): int
188+
{
189+
if (Coerceable::stringToInt($value)) {
190+
return \intval($value);
191+
}
192+
193+
throw new TypeError('Only numbers with no fractional part can be coerced from a string to an int, given value: ' . Debug::sanitizeData($value));
194+
}
195+
196+
/**
197+
* @pure
198+
* @throws TypeError
199+
*/
200+
public static function stringToFloat(string $value): float
201+
{
202+
if (Coerceable::stringToFloat($value)) {
203+
return \floatval($value);
204+
}
205+
206+
throw new TypeError('Only numbers with no fractional part can be coerced from a string to a float, given value: ' . Debug::sanitizeData($value));
144207
}
145208
}

0 commit comments

Comments
 (0)