Passed
Push — master ( bb7d7e...4baabf )
by Adam
01:42
created

Input::getExistsFilename()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 8
nc 2
nop 3
dl 0
loc 14
rs 9.4285
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
    public static function getFilename($message, $default = 'output')
79
    {
80
        echo $message.' [Default: '.$default.']: ';
81
82
        do {
83
            $input = trim(fgets(/** @scrutinizer ignore-type */ STDIN));
84
85
            /*
86
             * Invalid characters in files:
87
             * (Windows)  \/:*?"<>|
88
             * (Linux)    /
89
             */
90
91
            $lastCharacter = substr($input, -1);
92
93
            // Only last character because / and \ are for folders
94
            $isInputWrong = $lastCharacter === '/' || $lastCharacter === '\\';
95
96
            // Running under Windows?
97
            if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
98
                // https://regex101.com/r/wR5d0J/2/
99
                $isInputWrong = $isInputWrong || preg_match('/[:*?"<>|]/', $input);
100
            }
101
102
            if (is_null($input) || empty($input)) {
103
                Text::debug('Using default input: '.$default);
104
                $input = $default;
105
            } elseif ($isInputWrong) {
106
                echo 'Please input valid filename: ';
107
            }
108
        } while ($isInputWrong);
109
110
        return $input;
111
    }
112
113
    /**
114
     * Get bytes number from unit conversation.
115
     *
116
     * @param string $input    User input e.g. '5B', '5MB'
117
     * @param int    $notation Notation type for kilo
118
     *
119
     * @return array
120
     */
121
    protected static function getBytesFromString($input, $notation = 1024)
122
    {
123
        $error = true;
124
        $bytes = 0;
125
126
        // https://regex101.com/r/v936BS/2
127
        if (preg_match('/^(?<number>\d+(?!\.+\,+\d*))\s*(?<unit>B|KB|MB|GB|TB)$/', $input, $matches)) {
128
            $error = false;
129
        }
130
131
        if ($error) {
132
            return array('error' => $error, 'bytes' => $bytes);
133
        }
134
135
        switch ($matches['unit']) {
136
            case 'KB':
137
                $bytes = $matches['number'] * $notation;
138
                break;
139
            case 'MB':
140
                $bytes = $matches['number'] * pow($notation, 2);
141
                break;
142
            case 'GB':
143
                $bytes = $matches['number'] * pow($notation, 3);
144
                break;
145
            case 'TB':
146
                $bytes = $matches['number'] * pow($notation, 4);
147
                break;
148
            // As Bytes
149
            default:
150
                $bytes = $matches['number'];
151
                break;
152
        }
153
154
        return array('error' => $error, 'bytes' => $bytes);
155
    }
156
157
    /**
158
     * Get number from User.
159
     *
160
     * @param string    $message Message for User what he must type
161
     * @param int|float $default Default number for empty input. Default is 0
162
     *
163
     * @return float Inserted number
164
     */
165
    public static function getNumber($message, $default = 0)
166
    {
167
        echo $message.' [Default: '.$default.']: ';
168
169
        do {
170
            $input = trim(fgets(/** @scrutinizer ignore-type */ STDIN));
171
172
            if (is_null($input) || empty($input)) {
173
                Text::debug('Using default input: '.$default);
174
                $input = $default;
175
            } elseif (!is_numeric($input)) {
176
                echo 'Please input number: ';
177
            }
178
        } while (!is_numeric($input));
179
180
        return (float) $input;
181
    }
182
183
    /**
184
     * Get User confirmation. Default is YES.
185
     *
186
     * @return bool Confirmation result
187
     */
188
    public static function getUserConfirm()
189
    {
190
        while (1) {
191
            echo 'Do you really want to continue? [Y/n]: ';
192
193
            $input = trim(fgets(/** @scrutinizer ignore-type */ STDIN));
194
195
            // Default is YES
196
            if (is_null($input) || empty($input) || strtolower($input) == 'y' || strtolower($input) == 'yes') {
197
                return true;
198
            } elseif (strtolower($input) == 'n' || strtolower($input) == 'no') {
199
                return false;
200
            }
201
        }
202
203
        // Fix missing return statement warning. Return true...
204
        return true;
205
    }
206
207
    /**
208
     * Get exists filename
209
     *
210
     * @param string $message       Message for User what he must type
211
     * @param string $default       Default filename for empty input. Default is 'output'
212
     * @param string $fileExtension File extension. Default is '.dat'
213
     *
214
     * @return string
215
     *
216
     * @see Input::getFilename()
217
     */
218
    public static function getExistsFilename($message, $default = 'output', $fileExtension = '.dat')
219
    {
220
        $filename = self::getFilename($message, $default);
221
222
        do {
223
            $error = false;
224
225
            if (!file_exists($filename.$fileExtension)) {
226
                $error = true;
227
                $filename = self::getFilename('Please type existing file', $default);
228
            }
229
        } while ($error);
230
231
        return $filename;
232
    }
233
234
    /**
235
     * Terminate script if User denied on confirmation.
236
     *
237
     * @see Input::getUserConfirm()
238
     */
239
    public static function dieOnDenyUserConfirm()
240
    {
241
        if (!self::getUserConfirm()) {
242
            die('Script terminated by user.');
243
        }
244
    }
245
}
246