Completed
Branch master (6cba54)
by Marcel
03:45 queued 01:30
created

Numeric::ensureFloat()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
namespace nochso\Omni;
3
4
/**
5
 * Numeric validates and converts mixed types to numeric types.
6
 */
7
class Numeric
8
{
9
    /**
10
     * Ensure integer or or float value by safely converting.
11
     *
12
     * Safe conversions to int or float:
13
     * 
14
     * ```
15
     * '-1'    => -1
16
     * '+00.0' => 0.0
17
     * '1'     => 1
18
     * ' 1 '    => 1
19
     * '01'    => 1
20
     * '0.1'   => 0.1
21
     * '.1'    => 0.1
22
     * ```
23
     * 
24
     * Invalid conversions:
25
     * 
26
     * ```
27
     * 'x'
28
     * '0a'
29
     * ''
30
     * '-'
31
     * ' '
32
     * '0+1'
33
     * '.'
34
     * ','
35
     * '0x0'
36
     * ```
37
     * 
38
     * @param mixed $value
39
     *
40
     * @throws \InvalidArgumentException If the value could not be safely converted to int or float.
41
     *
42
     * @return int|float
43
     */
44
    public static function ensure($value)
45
    {
46
        if (is_int($value) || is_float($value)) {
47
            return $value;
48
        }
49
        $value = trim($value);
50
        if (is_numeric($value)) {
51
            // Results in either int or float
52
            return $value + 0;
53
        }
54
        throw new \InvalidArgumentException(sprintf(
55
            'Expecting value of type int, float or compatible, got variable of type %s instead.',
56
            Type::summarize($value)
57
        ));
58
    }
59
60
    /**
61
     * ensureInteger values by safely converting.
62
     * 
63
     * These are safe conversions because no information is lost:
64
     * 
65
     * ```
66
     * 1      => 1
67
     * '1.00' => 1
68
     * '1'    => 1
69
     * '+1'   => 1
70
     * ```
71
     * 
72
     * These are invalid conversions because information would be lost:
73
     * 
74
     * ```
75
     * 0.1
76
     * '0.1'
77
     * '.1'
78
     * ```
79
     * 
80
     * If you don't care about this, you should cast to int instead: `(int)$value`
81
     * 
82
     * @param mixed $value
83
     *
84
     * @throws \InvalidArgumentException If floating point information would be lost, i.e. it does not look like an integer.
85
     *
86
     * @return int
87
     */
88
    public static function ensureInteger($value)
89
    {
90
        $numeric = self::ensure($value);
91
        if ((float) (int) $numeric !== (float) $numeric) {
92
            throw new \InvalidArgumentException(sprintf(
93
            "Could not safely convert value '%s' of type '%s' to integer because of trailing decimal places.",
94
            $value,
95
            Type::summarize($value)
96
        ));
97
        }
98
        return (int) $numeric;
99
    }
100
101
    /**
102
     * ensureFloat values by safely converting.
103
     *
104
     * For example the following conversions are safe:
105
     * 
106
     * ```
107
     * '0'     => 0.0
108
     * '0.0'   => 0.0
109
     * '0.1'   => 0.1
110
     *  '-5.1' => 5.1
111
     * ```
112
     * 
113
     * @param mixed $value
114
     *
115
     * @throws \InvalidArgumentException If value could not be safely converted to float.
116
     *
117
     * @return float
118
     */
119
    public static function ensureFloat($value)
120
    {
121
        return (float) self::ensure($value);
122
    }
123
}
124