Completed
Push — master ( b3ae6a...42714b )
by Mihail
03:01
created

File::getMd5()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 5
nc 2
nop 1
1
<?php
2
3
namespace Ffcms\Core\Helper\FileSystem;
4
5
use Ffcms\Core\Helper\Type\Arr;
6
use Ffcms\Core\Helper\Type\Str;
7
8
/**
9
 * Class File. Provide methods to work with files in current filesystem.
10
 * @package Ffcms\Core\Helper
11
 */
12
class File
13
{
14
15
    /**
16
     * Read file content from local storage
17
     * @param $path
18
     * @return bool|string
19
     */
20
    public static function read($path)
21
    {
22
        $path = Normalize::diskFullPath($path);
23
24
        if (!self::exist($path)) {
25
            return false;
26
        }
27
28
        return @file_get_contents($path);
29
    }
30
31
    /**
32
     * Check if $path is exist and readable in filesystem
33
     * @param string $path
34
     * @return bool
35
     */
36
    public static function exist($path)
37
    {
38
        $path = Normalize::diskFullPath($path);
39
        return (file_exists($path) && is_readable($path) && is_file($path));
40
    }
41
42
    /**
43
     * Alias for exist method
44
     * @param string $path
45
     * @return bool
46
     */
47
    public static function readable($path) {
48
        return self::exist($path);
49
    }
50
51
    /**
52
     * Check is file writable
53
     * @param string $path
54
     * @return bool
55
     */
56 View Code Duplication
    public static function writable($path)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
57
    {
58
        $path = Normalize::diskFullPath($path);
59
60
        if (!self::exist($path)) {
61
            return false;
62
        }
63
64
        return is_writable($path);
65
    }
66
67
    /**
68
     * Check is file executable
69
     * @param string $path
70
     * @return bool
71
     */
72
    public static function executable($path)
73
    {
74
        $path = Normalize::diskFullPath($path);
75
76
        if (!self::exist($path)) {
77
            return false;
78
        }
79
80
        return is_executable($path);
81
    }
82
83
    /**
84
     * Write $content to file in $path
85
     * @param string $path
86
     * @param null|string $content
87
     * @param null|int $flags
88
     * @return int
89
     */
90
    public static function write($path, $content = null, $flags = null)
91
    {
92
        $path = Normalize::diskFullPath($path);
93
94
        $pathArray = explode(DIRECTORY_SEPARATOR, $path);
95
        array_pop($pathArray);
96
        $pathName = implode(DIRECTORY_SEPARATOR, $pathArray);
97
98
        if (!Directory::exist($pathName)) {
99
            Directory::create($pathName);
100
        }
101
        return @file_put_contents($path, $content, $flags);
102
    }
103
104
    /**
105
     * Remove file
106
     * @param string $path
107
     * @return bool
108
     */
109
    public static function remove($path)
110
    {
111
        $path = Normalize::diskFullPath($path);
112
113
        if (!self::exist($path)) {
114
            return false;
115
        }
116
        return unlink($path);
117
    }
118
119
120
    /**
121
     * Alternative of functions include, require, include_once and etc in 1 function
122
     * @param string $path
123
     * @param bool|false $return
124
     * @param bool|false $once
125
     * @return bool|mixed
126
     */
127
    public static function inc($path, $return = false, $once = false)
128
    {
129
        $path = Normalize::diskFullPath($path);
130
131
        if (!self::exist($path)) {
132
            return false;
133
        }
134
135
        if ($return === true) {
136
            return $once === true ? require_once($path) : require $path;
137
        } else {
138
            ($once == true) ? require_once($path) : require $path;
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
139
        }
140
    }
141
142
    /**
143
     * Get file make time in unix timestamp
144
     * @param string $path
145
     * @return int
146
     */
147
    public static function mTime($path)
148
    {
149
        $path = Normalize::diskFullPath($path);
150
        if (!self::exist($path)) {
151
            return 0;
152
        }
153
154
        return filemtime($path);
155
    }
156
157
    /**
158
     * Recursive scan directory, based on $path and allowed extensions $ext or without it
159
     * @param string $path
160
     * @param array $ext
161
     * @param bool $returnRelative
162
     * @param $files
163
     * @return array
164
     */
165
    public static function listFiles($path, array $ext = null, $returnRelative = false, &$files = [])
166
    {
167
        $path = Normalize::diskFullPath($path);
168
169
        if (!Directory::exist($path)) {
170
            return [];
171
        }
172
173
        $dir = opendir($path . '/.');
174
        while ($item = readdir($dir)) {
175
            if (is_file($sub = $path . '/' . $item)) {
176
                $item_ext = Str::lastIn($item, '.');
177
                if ($ext === null || Arr::in($item_ext, $ext)) {
0 ignored issues
show
Security Bug introduced by
It seems like $item_ext defined by \Ffcms\Core\Helper\Type\Str::lastIn($item, '.') on line 176 can also be of type false; however, Ffcms\Core\Helper\Type\Arr::in() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
178
                    if ($returnRelative) {
179
                        $files[] = $item;
180
                    } else {
181
                        $files[] = $path . DIRECTORY_SEPARATOR . $item;
182
                    }
183
                }
184
            } else {
185
                if ($item !== '.' && $item !== '..') {
186
                    self::listFiles($sub, $ext, $returnRelative, $files);
187
                }
188
            }
189
        }
190
191
        return $files;
192
    }
193
194
    /**
195
     * Get file size in bytes
196
     * @param string $path
197
     * @return int
198
     */
199
    public static function size($path)
200
    {
201
        $path = Normalize::diskFullPath($path);
202
203
        if (!self::exist($path)) {
204
            return 0;
205
        }
206
207
        return filesize($path);
208
    }
209
210
    /**
211
     * Get file md5 hash
212
     * @param string $path
213
     * @return bool|string
214
     */
215
    public static function getMd5($path)
216
    {
217
        $path = Normalize::diskFullPath($path);
218
219
        if (!self::exist($path)) {
220
            return false;
221
        }
222
223
        return md5_file($path);
224
    }
225
226
    /**
227
     * Get data from remote $url by curl library
228
     * @param string $url
229
     * @return mixed|null|false
230
     */
231
    public static function getFromUrl($url)
232
    {
233
        // check is valid url
234
        if (!filter_var($url, FILTER_VALIDATE_URL) || !function_exists('curl_init')) {
235
            return null;
236
        }
237
238
        // initialize curl & set required options and target url
239
        $curl = \curl_init();
240
        \curl_setopt($curl, CURLOPT_URL, $url);
241 View Code Duplication
        if (Str::startsWith('https', $url)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
242
            \curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
243
            \curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
244
        }
245
        \curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
246
        \curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 5);
247
        \curl_setopt($curl, CURLOPT_HEADER, 0);
248
        \curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)');
249
        \curl_setopt($curl, CURLOPT_FAILONERROR, true);
250
        \curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
251
        \curl_setopt($curl, CURLOPT_AUTOREFERER, true);
252
        \curl_setopt($curl, CURLOPT_TIMEOUT, 10);
253
        $content = \curl_exec($curl);
254
        \curl_close($curl);
255
256
        return $content;
257
    }
258
259
    /**
260
     * Download file from $url and save it into $path
261
     * @param string $url
262
     * @param string $path
263
     * @return bool
264
     */
265
    public static function saveFromUrl($url, $path)
266
    {
267
        if (!filter_var($url, FILTER_VALIDATE_URL) || !function_exists('curl_init')) {
268
            return false;
269
        }
270
271
        $path = Normalize::diskFullPath($path);
272
        // check if upload directory is exists
273
        $dir = dirname($path);
274
        if (!Directory::exist($dir)) {
275
            Directory::create($dir);
276
        }
277
        // initialize stream resource
278
        $stream = @fopen($path, 'w');
279
        // initialize curl & set required options, target url, destination save stream
280
        $curl = \curl_init();
281
        \curl_setopt($curl, CURLOPT_URL, $url);
282 View Code Duplication
        if (Str::startsWith('https', $url)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
283
            \curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
284
            \curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
285
        }
286
        \curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
287
        \curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 5);
288
        \curl_setopt($curl, CURLOPT_HEADER, 0);
289
        \curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322');
290
        \curl_setopt($curl, CURLOPT_FAILONERROR, true);
291
        \curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
292
        \curl_setopt($curl, CURLOPT_AUTOREFERER, true);
293
        \curl_setopt($curl, CURLOPT_TIMEOUT, 10);
294
        // set destination file path
295
        \curl_setopt($curl, CURLOPT_FILE, $stream);
296
        \curl_exec($curl);
297
        \curl_close($curl);
298
        fclose($stream);
299
300
        return true;
301
    }
302
303
}