Completed
Push — master ( 5f1b15...566d1a )
by Mihail
40:15
created

File::copy()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 15
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 9
nc 2
nop 2
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
     * Copy file from source to target destination
106
     * @param string $source
107
     * @param string $target
108
     * @return bool
109
     */
110
    public static function copy($source, $target)
111
    {
112
        $source = Normalize::diskFullPath($source);
113
        $target = Normalize::diskFullPath($target);
114
115
        // check if target directory exist & create new if not
116
        $targetArray = explode(DIRECTORY_SEPARATOR, $target);
117
        array_pop($targetArray);
118
        $targetDir = implode(DIRECTORY_SEPARATOR, $targetArray);
119
        if (!Directory::exist($targetDir)) {
120
            Directory::create($targetDir, 0777);
121
        }
122
123
        return copy($source, $target);
124
    }
125
126
    /**
127
     * Remove file
128
     * @param string $path
129
     * @return bool
130
     */
131
    public static function remove($path)
132
    {
133
        $path = Normalize::diskFullPath($path);
134
135
        if (!self::exist($path)) {
136
            return false;
137
        }
138
        return unlink($path);
139
    }
140
141
142
    /**
143
     * Alternative of functions include, require, include_once and etc in 1 function
144
     * @param string $path
145
     * @param bool|false $return
146
     * @param bool|false $once
147
     * @return bool|mixed
148
     */
149
    public static function inc($path, $return = false, $once = false)
150
    {
151
        $path = Normalize::diskFullPath($path);
152
153
        if (!self::exist($path)) {
154
            return false;
155
        }
156
157
        if ($return === true) {
158
            return $once === true ? require_once($path) : require $path;
159
        } else {
160
            ($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...
161
        }
162
    }
163
164
    /**
165
     * Get file make time in unix timestamp
166
     * @param string $path
167
     * @return int
168
     */
169
    public static function mTime($path)
170
    {
171
        $path = Normalize::diskFullPath($path);
172
        if (!self::exist($path)) {
173
            return 0;
174
        }
175
176
        return filemtime($path);
177
    }
178
179
    /**
180
     * Recursive scan directory, based on $path and allowed extensions $ext or without it
181
     * @param string $path
182
     * @param array $ext
183
     * @param bool $returnRelative
184
     * @param $files
185
     * @return array
186
     */
187
    public static function listFiles($path, array $ext = null, $returnRelative = false, &$files = [])
188
    {
189
        $path = Normalize::diskFullPath($path);
190
191
        if (!Directory::exist($path)) {
192
            return [];
193
        }
194
195
        $dir = opendir($path . '/.');
196
        while ($item = readdir($dir)) {
197
            if (is_file($sub = $path . '/' . $item)) {
198
                $item_ext = Str::lastIn($item, '.');
199
                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 198 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...
200
                    if ($returnRelative) {
201
                        $files[] = $item;
202
                    } else {
203
                        $files[] = $path . DIRECTORY_SEPARATOR . $item;
204
                    }
205
                }
206
            } else {
207
                if ($item !== '.' && $item !== '..') {
208
                    self::listFiles($sub, $ext, $returnRelative, $files);
209
                }
210
            }
211
        }
212
213
        return $files;
214
    }
215
216
    /**
217
     * Get file size in bytes
218
     * @param string $path
219
     * @return int
220
     */
221
    public static function size($path)
222
    {
223
        $path = Normalize::diskFullPath($path);
224
225
        if (!self::exist($path)) {
226
            return 0;
227
        }
228
229
        return filesize($path);
230
    }
231
232
    /**
233
     * Get file md5 hash
234
     * @param string $path
235
     * @return bool|string
236
     */
237
    public static function getMd5($path)
238
    {
239
        $path = Normalize::diskFullPath($path);
240
241
        if (!self::exist($path)) {
242
            return false;
243
        }
244
245
        return md5_file($path);
246
    }
247
248
    /**
249
     * Get data from remote $url by curl library
250
     * @param string $url
251
     * @return mixed|null|false
252
     */
253
    public static function getFromUrl($url)
254
    {
255
        // check is valid url
256
        if (!filter_var($url, FILTER_VALIDATE_URL) || !function_exists('curl_init')) {
257
            return null;
258
        }
259
260
        // initialize curl & set required options and target url
261
        $curl = \curl_init();
262
        \curl_setopt($curl, CURLOPT_URL, $url);
263 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...
264
            \curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
265
            \curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
266
        }
267
        \curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
268
        \curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 5);
269
        \curl_setopt($curl, CURLOPT_HEADER, 0);
270
        \curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)');
271
        \curl_setopt($curl, CURLOPT_FAILONERROR, true);
272
        \curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
273
        \curl_setopt($curl, CURLOPT_AUTOREFERER, true);
274
        \curl_setopt($curl, CURLOPT_TIMEOUT, 10);
275
        $content = \curl_exec($curl);
276
        \curl_close($curl);
277
278
        return $content;
279
    }
280
281
    /**
282
     * Download file from $url and save it into $path
283
     * @param string $url
284
     * @param string $path
285
     * @return bool
286
     */
287
    public static function saveFromUrl($url, $path)
288
    {
289
        if (!filter_var($url, FILTER_VALIDATE_URL) || !function_exists('curl_init')) {
290
            return false;
291
        }
292
293
        $path = Normalize::diskFullPath($path);
294
        // check if upload directory is exists
295
        $dir = dirname($path);
296
        if (!Directory::exist($dir)) {
297
            Directory::create($dir);
298
        }
299
        // initialize stream resource
300
        $stream = @fopen($path, 'w');
301
        // initialize curl & set required options, target url, destination save stream
302
        $curl = \curl_init();
303
        \curl_setopt($curl, CURLOPT_URL, $url);
304 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...
305
            \curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
306
            \curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
307
        }
308
        \curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
309
        \curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 5);
310
        \curl_setopt($curl, CURLOPT_HEADER, 0);
311
        \curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322');
312
        \curl_setopt($curl, CURLOPT_FAILONERROR, true);
313
        \curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
314
        \curl_setopt($curl, CURLOPT_AUTOREFERER, true);
315
        \curl_setopt($curl, CURLOPT_TIMEOUT, 10);
316
        // set destination file path
317
        \curl_setopt($curl, CURLOPT_FILE, $stream);
318
        \curl_exec($curl);
319
        \curl_close($curl);
320
        fclose($stream);
321
322
        return true;
323
    }
324
325
}