Input::isFilenameWrong()   A
last analyzed

Complexity

Conditions 4
Paths 6

Size

Total Lines 20
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 5
nc 6
nop 1
dl 0
loc 20
rs 10
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
require_once 'Text.php';
14
15
/**
16
 * Functions for receiving input from User.
17
 */
18
class Input
19
{
20
    /**
21
     * Get file size from User.
22
     *
23
     * @param string $message Message for User what he must type
24
     * @param string $default Default file size for empty input. Default is '1MB'
25
     *
26
     * @return int|string Inserted file size in bytes
27
     *
28
     * @see Input::getBytesFromString()
29
     */
30
    public static function getFileSize($message, $default = '1MB')
31
    {
32
        echo $message.' [Default: '.$default.']: ';
33
34
        do {
35
            $input = trim(fgets(/** @scrutinizer ignore-type */ STDIN));
36
37
            $isDefault = false;
38
39
            if (is_null($input) || empty($input)) {
40
                Text::debug('Using default input: '.$default);
41
                $isDefault = true;
42
                break;
43
            }
44
45
            $checkInput = self::getBytesFromString($input);
46
47
            if (!$checkInput['error']) {
48
                $input = $checkInput['bytes'];
49
                break;
50
            }
51
52
            echo 'Please input valid file size: ';
53
        } while (1);
54
55
        if ($isDefault) {
56
            // Check $default just for sure
57
            $checkDefault = self::getBytesFromString($default);
58
59
            // 1 MB in bytes
60
            $input = 1048576;
61
62
            if (!$checkDefault['error']) {
63
                $input = $checkDefault['bytes'];
64
            }
65
        }
66
67
        return $input;
68
    }
69
70
    /**
71
     * Get valid filename from User.
72
     *
73
     * @param string $message Message for User what he must type
74
     * @param string $default Default filename for empty input. Default is 'output'
75
     *
76
     * @return string Inserted filename
77
     *
78
     * @see Input::isFilenameWrong()
79
     */
80
    public static function getFilename($message, $default = 'output')
81
    {
82
        echo $message.' [Default: '.$default.']: ';
83
84
        do {
85
            $input = trim(fgets(/** @scrutinizer ignore-type */ STDIN));
86
87
            // Check for wrong filename based on OS
88
            $isInputWrong = self::isFilenameWrong($input);
89
90
            if (is_null($input) || empty($input)) {
91
                Text::debug('Using default input: '.$default);
92
                $input = $default;
93
            } elseif ($isInputWrong) {
94
                echo 'Please input valid filename: ';
95
            }
96
        } while ($isInputWrong);
97
98
        return $input;
99
    }
100
101
    /**
102
     * Get bytes number from unit conversation.
103
     *
104
     * @param string $input    User input e.g. '5B', '5MB'
105
     * @param int    $notation Notation type for kilo
106
     *
107
     * @return array
108
     */
109
    public static function getBytesFromString($input, $notation = 1024)
110
    {
111
        $error = true;
112
        $bytes = 0;
113
114
        // https://regex101.com/r/v936BS/2
115
        if (preg_match('/^(?<number>\d+(?!\.+\,+\d*))\s*(?<unit>B|KB|MB|GB|TB)$/', $input, $matches)) {
116
            $error = false;
117
        }
118
119
        if ($error) {
120
            return array('error' => $error, 'bytes' => $bytes);
121
        }
122
123
        switch ($matches['unit']) {
124
            case 'KB':
125
                $bytes = $matches['number'] * $notation;
126
                break;
127
            case 'MB':
128
                $bytes = $matches['number'] * pow($notation, 2);
129
                break;
130
            case 'GB':
131
                $bytes = $matches['number'] * pow($notation, 3);
132
                break;
133
            case 'TB':
134
                $bytes = $matches['number'] * pow($notation, 4);
135
                break;
136
            // As Bytes
137
            default:
138
                $bytes = $matches['number'];
139
                break;
140
        }
141
142
        return array('error' => $error, 'bytes' => $bytes);
143
    }
144
145
    /**
146
     * Get number from User.
147
     *
148
     * @param string    $message Message for User what he must type
149
     * @param int|float $default Default number for empty input. Default is 0
150
     *
151
     * @return float Inserted number
152
     */
153
    public static function getNumber($message, $default = 0)
154
    {
155
        echo $message.' [Default: '.$default.']: ';
156
157
        do {
158
            $input = trim(fgets(/** @scrutinizer ignore-type */ STDIN));
159
160
            if (is_null($input) || empty($input)) {
161
                Text::debug('Using default input: '.$default);
162
                $input = $default;
163
            } elseif (!is_numeric($input)) {
164
                echo 'Please input number: ';
165
            }
166
        } while (!is_numeric($input));
167
168
        return (float) $input;
169
    }
170
171
    /**
172
     * Get User confirmation. Default is YES.
173
     *
174
     * @return bool Confirmation result
175
     */
176
    public static function getUserConfirm()
177
    {
178
        while (1) {
179
            echo 'Do you really want to continue? [Y/n]: ';
180
181
            $input = trim(fgets(/** @scrutinizer ignore-type */ STDIN));
182
183
            // Default is YES
184
            if (is_null($input) || empty($input) || strtolower($input) == 'y' || strtolower($input) == 'yes') {
185
                return true;
186
            } elseif (strtolower($input) == 'n' || strtolower($input) == 'no') {
187
                return false;
188
            }
189
        }
190
191
        // Fix missing return statement warning. Return true...
192
        return true;
193
    }
194
195
    /**
196
     * Check for wrong filename based on OS.
197
     *
198
     * @param string $input User filename input
199
     *
200
     * @return bool Is filename wrong?
201
     */
202
    public static function isFilenameWrong($input)
203
    {
204
        /*
205
         * Invalid characters in files:
206
         * (Windows)  \/:*?"<>|
207
         * (Linux)    /
208
         */
209
210
        $lastCharacter = substr($input, -1);
211
212
        // Only last character because / and \ are for folders
213
        $isInputWrong = $lastCharacter === '/' || $lastCharacter === '\\';
214
215
        // Running under Windows?
216
        if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
217
            // https://regex101.com/r/wR5d0J/2/
218
            $isInputWrong = $isInputWrong || preg_match('/[:*?"<>|]/', $input);
219
        }
220
221
        return $isInputWrong;
222
    }
223
224
    /**
225
     * Get exists filename.
226
     *
227
     * @param string $message       Message for User what he must type
228
     * @param string $default       Default filename for empty input. Default is 'output'
229
     * @param string $fileExtension File extension. Default is '.dat'
230
     *
231
     * @return string
232
     *
233
     * @see Input::getFilename()
234
     */
235
    public static function getExistsFilename($message, $default = 'output', $fileExtension = '.dat')
236
    {
237
        $filename = self::getFilename($message, $default);
238
239
        do {
240
            $error = false;
241
242
            if (!file_exists($filename.$fileExtension)) {
243
                $error = true;
244
                $filename = self::getFilename('Please type existing file', $default);
245
            }
246
        } while ($error);
247
248
        return $filename;
249
    }
250
251
    /**
252
     * Terminate script if User denied on confirmation.
253
     *
254
     * @see Input::getUserConfirm()
255
     */
256
    public static function dieOnDenyUserConfirm()
257
    {
258
        if (!self::getUserConfirm()) {
259
            die('Script terminated by user.');
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
260
        }
261
    }
262
}
263