Completed
Push — master ( 838969...074806 )
by Lorenzo
02:23
created

FileHelper   C

Complexity

Total Complexity 63

Size/Duplication

Total Lines 403
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
wmc 63
lcom 1
cbo 1
dl 0
loc 403
rs 5.8893
c 0
b 0
f 0

15 Methods

Rating   Name   Duplication   Size   Complexity  
B getPathinfoPart() 0 13 9
A getDirname() 0 4 1
A getFilename() 0 4 1
A getFilenameWithoutExtension() 0 4 1
A getFilenameExtension() 0 4 1
C hasExtension() 0 26 7
B changeExtension() 0 17 5
A unlinkSafe() 0 12 3
A fileExistsSafe() 0 12 4
C findFiles() 0 43 13
C filePutContentsSafe() 0 29 7
A getMimeType() 0 17 4
A getMimeTypeByFinfo() 0 13 3
A getMimeTypeByMimeContentType() 0 7 2
A toLower() 0 7 2

How to fix   Complexity   

Complex Class

Complex classes like FileHelper often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use FileHelper, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Padosoft\Io;
4
5
/**
6
 * Helper Class FileHelper
7
 * @package Padosoft\Io
8
 */
9
class FileHelper
10
{
11
    public static $arrMimeType = array(
12
13
        'txt' => 'text/plain',
14
        'htm' => 'text/html',
15
        'html' => 'text/html',
16
        'php' => 'text/html',
17
        'css' => 'text/css',
18
        'js' => 'application/javascript',
19
        'json' => 'application/json',
20
        'xml' => 'application/xml',
21
        'swf' => 'application/x-shockwave-flash',
22
        'flv' => 'video/x-flv',
23
24
        // images
25
        'png' => 'image/png',
26
        'jpe' => 'image/jpeg',
27
        'jpeg' => 'image/jpeg',
28
        'jpg' => 'image/jpeg',
29
        'gif' => 'image/gif',
30
        'bmp' => 'image/bmp',
31
        'ico' => 'image/vnd.microsoft.icon',
32
        'tiff' => 'image/tiff',
33
        'tif' => 'image/tiff',
34
        'svg' => 'image/svg+xml',
35
        'svgz' => 'image/svg+xml',
36
37
        // archives
38
        'zip' => 'application/zip',
39
        'rar' => 'application/x-rar-compressed',
40
        'exe' => 'application/x-msdownload',
41
        'msi' => 'application/x-msdownload',
42
        'cab' => 'application/vnd.ms-cab-compressed',
43
44
        // audio/video
45
        'mp3' => 'audio/mpeg',
46
        'qt' => 'video/quicktime',
47
        'mov' => 'video/quicktime',
48
49
        // adobe
50
        'pdf' => 'application/pdf',
51
        'psd' => 'image/vnd.adobe.photoshop',
52
        'ai' => 'application/postscript',
53
        'eps' => 'application/postscript',
54
        'ps' => 'application/postscript',
55
56
        // ms office
57
        'doc' => 'application/msword',
58
        'rtf' => 'application/rtf',
59
        'xls' => 'application/vnd.ms-excel',
60
        'ppt' => 'application/vnd.ms-powerpoint',
61
62
        // open office
63
        'odt' => 'application/vnd.oasis.opendocument.text',
64
        'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
65
    );
66
67
    /**
68
     * Simple pathinfo wrapper.
69
     * @param string $filePath
70
     * @param int $fileInfOoptions
71
     * @return string
72
     * @see http://php.net/manual/en/function.pathinfo.php
73
     */
74
    public static function getPathinfoPart(string $filePath, int $fileInfOoptions) : string
75
    {
76
        if ($filePath === null || $filePath == '' || is_dir($filePath) || DirHelper::endsWithSlash($filePath)) {
77
            return '';
78
        }
79
80
        $info = pathinfo($filePath, $fileInfOoptions);
81
82
        if ($info == '.' && $fileInfOoptions == PATHINFO_DIRNAME) {
83
            return '';
84
        }
85
        return ($info !== null && $info != '') ? $info : '';
86
    }
87
88
    /**
89
     * Return the file name of file (without path and without extension).
90
     * Return empty string if $filePath is null, empty or is a directory.
91
     * Ex.: /public/upload/pippo.txt return '/public/upload'
92
     * @param string $filePath
93
     * @return string
94
     */
95
    public static function getDirname(string $filePath) : string
96
    {
97
        return self::getPathinfoPart($filePath, PATHINFO_DIRNAME);
98
    }
99
100
    /**
101
     * Return the file name of file (without path and with extension).
102
     * Return empty string if $filePath is null, empty or is a directory.
103
     * Ex.: /public/upload/pippo.txt return 'pippo.txt'
104
     * @param string $filePath
105
     * @return string
106
     */
107
    public static function getFilename(string $filePath) : string
108
    {
109
        return self::getPathinfoPart($filePath, PATHINFO_BASENAME);
110
    }
111
112
    /**
113
     * Return the file name of file (without path and without extension).
114
     * Return empty string if $filePath is null, empty or is a directory.
115
     * Ex.: /public/upload/pippo.txt return 'pippo'
116
     * @param string $filePath
117
     * @return string
118
     */
119
    public static function getFilenameWithoutExtension(string $filePath) : string
120
    {
121
        return self::getPathinfoPart($filePath, PATHINFO_FILENAME);
122
    }
123
124
    /**
125
     * Return the file name of file (without path and without extension).
126
     * Return empty string if $filePath is null, empty or is a directory.
127
     * Ex.: /public/upload/pippo.txt return '.txt'
128
     * @param string $filePath
129
     * @return string
130
     */
131
    public static function getFilenameExtension(string $filePath) : string
132
    {
133
        return self::getPathinfoPart($filePath, PATHINFO_EXTENSION);
134
    }
135
136
    /**
137
     * Returns whether the path has an extension.
138
     *
139
     * @param string $path The path string
140
     * @param string|array|null $extensions If null or not provided, checks if an
141
     *                                       extension exists, otherwise checks for
142
     *                                       the specified extension or array of extensions
143
     *                                       (with or without leading dot)
144
     * @param bool $ignoreCase Whether to ignore case-sensitivity
145
     *                                       (Requires mbstring extension for correct
146
     *                                       multi-byte character handling in extension)
147
     *
148
     * @return bool true if the path has an (or the specified) extension, otherwise false
149
     *
150
     * @see https://github.com/laradic/support/blob/master/src/Path.php
151
     */
152
    public static function hasExtension(string $path, $extensions = null, bool $ignoreCase = false) : bool
153
    {
154
        if ('' === $path) {
155
            return false;
156
        }
157
        $actualExtension = self::getFilenameExtension($path);
158
        if ($ignoreCase) {
159
            $actualExtension  = self::toLower($actualExtension );
160
        }
161
        // Only check if path has any extension
162
        if (null === $extensions) {
163
            return !empty($actualExtension);
164
        }
165
        // Make an array of extensions
166
        if (!is_array($extensions)) {
167
            $extensions = [ $extensions ];
168
        }
169
        foreach ($extensions as $key => $extension) {
170
            if ($ignoreCase) {
171
                $extension = self::toLower($extension);
172
            }
173
            // remove leading '.' in extensions array
174
            $extensions[ $key ] = ltrim($extension, '.');
175
        }
176
        return in_array($actualExtension, $extensions);
177
    }
178
    /**
179
     * Changes the extension of a path string.
180
     *
181
     * @param string $path The path string with filename.ext to change
182
     * @param string $extension New extension (with or without leading dot)
183
     *
184
     * @return string The path string with new file extension
185
     *
186
     * @see https://github.com/laradic/support/blob/master/src/Path.php
187
     */
188
    public static function changeExtension($path, $extension)
189
    {
190
        if ('' === $path) {
191
            return '';
192
        }
193
        $actualExtension = self::getFilenameExtension($path);
194
        $extension = ltrim($extension, '.');
195
        // No extension for paths
196
        if ('/' == substr($path, -1)) {
197
            return $path;
198
        }
199
        // No actual extension in path
200
        if (empty($actualExtension)) {
201
            return $path . ('.' == substr($path, -1) ? '' : '.') . $extension;
202
        }
203
        return substr($path, 0, -strlen($actualExtension)) . $extension;
204
    }
205
206
    /**
207
     * unlink file if exists.
208
     * Return false if exists and unlink fails or if filePath is a dir.
209
     * @param string $filePath
210
     * @return bool
211
     */
212
    public static function unlinkSafe(string $filePath) : bool
213
    {
214
        if (!FileHelper::fileExistsSafe($filePath)) {
215
            return false;
216
        }
217
218
        if (DirHelper::isDirSafe($filePath)) {
219
            return false;
220
        }
221
222
        return unlink($filePath);
223
    }
224
225
    /**
226
     * Check if passed file exists or not.
227
     * If dir passed return false.
228
     * @param string $filePath
229
     * @return bool
230
     */
231
    public static function fileExistsSafe(string $filePath) : bool
232
    {
233
        if ($filePath === null || $filePath == '') {
234
            return false;
235
        }
236
237
        if (DirHelper::isDirSafe($filePath)) {
238
            return false;
239
        }
240
241
        return file_exists($filePath);
242
    }
243
244
    /**
245
     * Find files matching a pattern (recursive with matched files in subdirs).
246
     * Returns an array containing the matched files (full path and not directories),
247
     * an empty array if no file matched or on error.
248
     * @param string $fileNamePattern if is null it set to base_path()/* if exists otherwise __DIR__/* . It support glob() string pattern.
249
     * @param int $flags glob() Valid flags
250
     * @return array of files (full path)
251
     */
252
    public static function findFiles(string $fileNamePattern, int $flags = 0)
253
    {
254
        $fallback = [];
255
256
        if (($fileNamePattern === null || $fileNamePattern == '') && function_exists('base_path')) {
257
            $fileNamePattern = DirHelper::addFinalSlash(base_path()) . '*';
258
        } elseif ($fileNamePattern === null || $fileNamePattern == '') {
259
            $fileNamePattern = __DIR__ . '/*';
260
        }
261
262
        if (DirHelper::endsWithSlash($fileNamePattern)) {
263
            $fileNamePattern .= '*';
264
        }
265
266
        $files = glob($fileNamePattern, $flags);
267
268
        //remove array of empty string
269
        $files = array_filter($files, function ($k) {
270
            return ($k !== null && $k != '');
271
        });
272
273
        if (empty($files)) {
274
            return $fallback;
275
        }
276
277
        foreach (glob(dirname($fileNamePattern) . '/*', GLOB_ONLYDIR | GLOB_NOSORT) as $dir) {
278
279
            if (empty($dir)) {
280
                continue;
281
            }
282
283
            $files = array_merge($files, self::findFiles($dir . '/' . basename($fileNamePattern), $flags));
284
            $files = array_filter($files, function ($k) {
285
                return ($k !== null && $k != '');
286
            });
287
        }
288
289
        $files = array_filter($files, function ($k) {
290
            return (!is_dir($k));
291
        });
292
293
        return $files === false ? $fallback : $files;
294
    }
295
296
    /**
297
     * Equals to file_put_contents but safe, i.e.
298
     * accept empty string and return false without raise an error,
299
     * accept a directory and return false without raise an error,
300
     * and if $forceCreateDirIfNotExists is set to true and path doesn't exists, file_put_contents fails
301
     * so, this class, try to create the complete path before save file.
302
     * @param string $filename file name including folder.
303
     * example :: /path/to/file/filename.ext or filename.ext
304
     * @param string $data The data to write.
305
     * @param bool $forceCreateDirIfNotExists if true and path not exists, try to create it.
306
     * @param string $modeMask The mask applied to dir if need to create some dir.
307
     * @param int $flags same flags used for file_put_contents.
308
     * @see more info: http://php.net/manual/en/function.file-put-contents.php
309
     * @return bool TRUE file created succesfully, return FALSE if failed to create file.
310
     */
311
    public static function filePutContentsSafe(
312
        string $filename,
313
        string $data,
314
        bool $forceCreateDirIfNotExists = true,
315
        string $modeMask = '0755',
316
        int $flags = 0
317
    ) : bool
318
    {
319
        if ($filename === null || $filename == '') {
320
            return false;
321
        }
322
323
        //check if a directory passed ($filename ends with slash)
324
        if (DirHelper::endsWithSlash($filename)) {
325
            return false;
326
        }
327
328
        $dirName = dirname($filename);
329
330
        if (!$forceCreateDirIfNotExists && !DirHelper::isDirSafe($dirName)) {
331
            return false;
332
        }
333
334
        if (!DirHelper::checkDirExistOrCreate(DirHelper::addFinalSlash($dirName), $modeMask)) {
335
            return false;
336
        }
337
338
        return file_put_contents($filename, $data, $flags);
339
    }
340
341
    /**
342
     * Return mime type of a passed file in optimized mode.
343
     * @param string $fullPathFile
344
     * @return string
345
     */
346
    public static function getMimeType(string $fullPathFile) : string
347
    {
348
        $mime_types = self::$arrMimeType;
349
        $ext = strtolower(self::getFilenameExtension($fullPathFile));
350
        if (array_key_exists($ext, $mime_types)) {
351
            return $mime_types[$ext];
352
        }
353
        $mimetype = self::getMimeTypeByMimeContentType($fullPathFile);
354
        if (isNotNullOrEmpty($mimetype)) {
355
            return $mimetype;
356
        }
357
        $mimetype = self::getMimeTypeByFinfo($fullPathFile);
358
        if (isNotNullOrEmpty($mimetype)) {
359
            return $mimetype;
360
        }
361
        return 'application/octet-stream';
362
    }
363
364
    /**
365
     * Return mime type of a passed file using finfo
366
     * @param string $fullPathFile
367
     * @return string return empty string if it fails.
368
     */
369
    public static function getMimeTypeByFinfo(string $fullPathFile) : string
370
    {
371
        if (!function_exists('finfo_open')) {
372
            return '';
373
        }
374
        $finfo = finfo_open(FILEINFO_MIME);
375
        $mimetype = finfo_file($finfo, $fullPathFile);
376
        finfo_close($finfo);
377
        if ($mimetype === false) {
378
            return '';
379
        }
380
        return $mimetype;
381
    }
382
383
    /**
384
     * Return mime type of a passed file using mime_content_type()
385
     * @param string $fullPathFile
386
     * @return string return empty string if it fails.
387
     */
388
    public static function getMimeTypeByMimeContentType(string $fullPathFile) : string
389
    {
390
        if (!function_exists('mime_content_type')) {
391
            return '';
392
        }
393
        return mime_content_type($fullPathFile);
394
    }
395
396
    /**
397
     * Converts string to lower-case (multi-byte safe if mbstring is installed).
398
     *
399
     * @param string $str The string
400
     *
401
     * @return string Lower case string
402
     * @see https://github.com/laradic/support/blob/master/src/Path.php
403
     */
404
    private static function toLower($str)
405
    {
406
        if (function_exists('mb_strtolower')) {
407
            return mb_strtolower($str, mb_detect_encoding($str));
408
        }
409
        return strtolower($str);
410
    }
411
}
412