Passed
Push — master ( a4178b...3fc425 )
by Adam
01:37
created

Input::getNumber()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 16
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 10
nc 3
nop 2
dl 0
loc 16
rs 8.8571
c 0
b 0
f 0
1
<?php
2
/**
3
 * Includes/Input.php.
4
 *
5
 * @author  Adam "Saibamen" Stachowicz <[email protected]>
6
 * @license MIT
7
 *
8
 * @link    https://github.com/Saibamen/Generate-Sort-Numbers
9
 */
10
11
namespace Includes;
12
13
/**
14
 * Functions for receiving input from User.
15
 */
16
class Input
17
{
18
    /**
19
     * Get number from User.
20
     *
21
     * @param string    $message Message for User what he must type
22
     * @param int|float $default Default number for empty input. Default is 0
23
     *
24
     * @return float Inserted number
25
     */
26
    public static function getNumber($message, $default = 0)
27
    {
28
        echo $message.' [Default: '.$default.']: ';
29
30
        do {
31
            $input = trim(fgets(STDIN));
0 ignored issues
show
Bug introduced by
Includes\STDIN of type string is incompatible with the type resource expected by parameter $handle of fgets(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

31
            $input = trim(fgets(/** @scrutinizer ignore-type */ STDIN));
Loading history...
32
33
            if (is_null($input) || empty($input)) {
34
                Text::debug('Using default input: '.$default);
35
                $input = $default;
36
            } elseif (!is_numeric($input)) {
37
                echo 'Please input number: ';
38
            }
39
        } while (!is_numeric($input));
40
41
        return (float) $input;
42
    }
43
44
    /**
45
     * Get file size from User.
46
     *
47
     * @param string $message Message for User what he must type
48
     * @param string $default Default file size for empty input. Default is '1MB'
49
     *
50
     * @return int Inserted file size in bytes
51
     *
52
     * @see Input::getBytesFromString()
53
     */
54
    public static function getFileSize($message, $default = '1MB')
55
    {
56
        echo $message.' [Default: '.$default.']: ';
57
58
        do {
59
            $input = trim(fgets(STDIN));
0 ignored issues
show
Bug introduced by
Includes\STDIN of type string is incompatible with the type resource expected by parameter $handle of fgets(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

59
            $input = trim(fgets(/** @scrutinizer ignore-type */ STDIN));
Loading history...
60
61
            $isDefault = false;
62
63
            if (is_null($input) || empty($input)) {
64
                Text::debug('Using default input: '.$default);
65
                $isDefault = true;
66
                break;
67
            }
68
69
            $checkInput = self::getBytesFromString($input);
70
71
            if (!$checkInput['error']) {
72
                $input = $checkInput['bytes'];
73
                break;
74
            }
75
76
            echo 'Please input valid file size: ';
77
78
        } while (1);
79
80
        if ($isDefault) {
81
            // Check $default just for sure
82
            $checkDefault = self::getBytesFromString($default);
83
84
            // 1 MB in bytes
85
            $input = 1048576;
86
87
            if (!$checkDefault['error']) {
88
                $input = $checkDefault['bytes'];
89
            }
90
        }
91
92
        return $input;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $input also could return the type string which is incompatible with the documented return type integer.
Loading history...
93
    }
94
95
    /**
96
     * Get valid filename from User.
97
     *
98
     * @param string $message Message for User what he must type
99
     * @param string $default Default filename for empty input. Default is 'output'
100
     *
101
     * @return string Inserted filename
102
     */
103
    public static function getFilename($message, $default = 'output')
104
    {
105
        echo $message.' [Default: '.$default.']: ';
106
107
        do {
108
            $input = trim(fgets(STDIN));
0 ignored issues
show
Bug introduced by
Includes\STDIN of type string is incompatible with the type resource expected by parameter $handle of fgets(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

108
            $input = trim(fgets(/** @scrutinizer ignore-type */ STDIN));
Loading history...
109
110
            /*
111
             * Invalid characters in files:
112
             * (Windows)  \/:*?"<>|
113
             * (Linux)    /
114
             */
115
116
            $lastCharacter = substr($input, -1);
117
118
            // Only last character because / and \ are for folders
119
            $isInputWrong = $lastCharacter === '/' || $lastCharacter === '\\';
120
121
            // Running under Windows?
122
            if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
123
                // https://regex101.com/r/wR5d0J/2/
124
                $isInputWrong = $isInputWrong || preg_match('/[:*?"<>|]/', $input);
125
            }
126
127
            if (is_null($input) || empty($input)) {
128
                Text::debug('Using default input: '.$default);
129
                $input = $default;
130
            } elseif ($isInputWrong) {
131
                echo 'Please input valid filename: ';
132
            }
133
        } while ($isInputWrong);
134
135
        return $input;
136
    }
137
138
    /**
139
     * Terminate script if User denied on confirmation.
140
     *
141
     * @see Input::getUserConfirm()
142
     */
143
    public static function dieOnDenyUserConfirm()
144
    {
145
        if (!self::getUserConfirm()) {
146
            die('Script terminated by user.');
147
        }
148
    }
149
150
    /**
151
     * Get User confirmation. Default is YES.
152
     *
153
     * @return bool Confirmation result
154
     */
155
    public static function getUserConfirm()
156
    {
157
        while (1) {
158
            echo 'Do you really want to continue? [Y/n]: ';
159
160
            $input = trim(fgets(STDIN));
0 ignored issues
show
Bug introduced by
Includes\STDIN of type string is incompatible with the type resource expected by parameter $handle of fgets(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

160
            $input = trim(fgets(/** @scrutinizer ignore-type */ STDIN));
Loading history...
161
162
            // Default is YES
163
            if (is_null($input) || empty($input) || strtolower($input) == 'y' || strtolower($input) == 'yes') {
164
                return true;
165
            } elseif (strtolower($input) == 'n' || strtolower($input) == 'no') {
166
                return false;
167
            }
168
        }
169
170
        // Fix missing return statement warning. Return true...
171
        return true;
172
    }
173
174
    /**
175
     * Get bytes number from unit conversation.
176
     *
177
     * @param string $input    User input e.g. '5B', '5MB'
178
     * @param int    $notation Notation type for kilo
179
     *
180
     * @return array
181
     */
182
    protected static function getBytesFromString($input, $notation = 1024)
183
    {
184
        $error = true;
185
        $bytes = 0;
186
187
        // https://regex101.com/r/v936BS/2
188
        if (preg_match('/^(?<number>\d+(?!\.+\,+\d*))\s*(?<unit>B|KB|MB|GB|TB)$/', $input, $matches)) {
189
            $error = false;
190
        }
191
192
        if ($error) {
193
            return array('error' => $error, 'bytes' => $bytes);
194
        }
195
196
        switch ($matches['unit']) {
197
            case 'KB':
198
                $bytes = $matches['number'] * $notation;
199
                break;
200
            case 'MB':
201
                $bytes = $matches['number'] * pow($notation, 2);
202
                break;
203
            case 'GB':
204
                $bytes = $matches['number'] * pow($notation, 3);
205
                break;
206
            case 'TB':
207
                $bytes = $matches['number'] * pow($notation, 4);
208
                break;
209
            // As Bytes
210
            default:
211
                $bytes = $matches['number'];
212
                break;
213
        }
214
215
        return array('error' => $error, 'bytes' => $bytes);
216
    }
217
}
218