Completed
Pull Request — master (#81)
by
unknown
14:25
created

FileHelper::normalizeOptions()   B

Complexity

Conditions 8
Paths 8

Size

Total Lines 21
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 21
rs 7.1428
c 0
b 0
f 0
cc 8
eloc 12
nc 8
nop 1
1
<?php
2
3
namespace the0rist\imperavi\helpers;
4
5
use the0rist\imperavi\actions\GetAction;
6
use yii\base\InvalidParamException;
7
use yii\helpers\BaseFileHelper;
8
use yii\helpers\StringHelper;
9
10
/**
11
 * File system helper
12
 *
13
 * @author Vasile Crudu <[email protected]>
14
 *
15
 * @link https://github.com/the0rist
16
 */
17
class FileHelper extends BaseFileHelper
18
{
19
    /**
20
     * @inheritdoc
21
     *
22
     * @param array $options {
23
     *
24
     * @type array $except
25
     * @type array $only
26
     * }
27
     */
28
    public static function findFiles($dir, $options = [], $type = GetAction::TYPE_IMAGES)
29
    {
30
        if (!is_dir($dir)) {
31
            throw new InvalidParamException('The dir argument must be a directory.');
32
        }
33
        $dir = rtrim($dir, DIRECTORY_SEPARATOR);
34
        if (isset($options['url'])) {
35
            $options['url'] = rtrim($options['url'], '/');
36
        }
37
        if (!isset($options['basePath'])) {
38
            $options['basePath'] = realpath($dir);
39
            // this should also be done only once
40
            $options = self::normalizeOptions($options);
41
        }
42
        $list = [];
43
        $handle = opendir($dir);
44
        if ($handle === false) {
45
            // @codeCoverageIgnoreStart
46
            throw new InvalidParamException('Unable to open directory: ' . $dir);
47
            // @codeCoverageIgnoreEnd
48
        }
49
        while (($file = readdir($handle)) !== false) {
50
            if ($file === '.' || $file === '..') {
51
                continue;
52
            }
53
            $path = $dir . DIRECTORY_SEPARATOR . $file;
54
            if (static::filterPath($path, $options)) {
55
                if (is_file($path)) {
56
                    if (isset($options['url'])) {
57
                        $url = str_replace([$options['basePath'], '\\'], [$options['url'], '/'], static::normalizePath($path));
58
59
                        if ($type === GetAction::TYPE_IMAGES) {
60
                            $list[] = [
61
                                'title' => $file,
62
                                'thumb' => $url,
63
                                'image' => $url
64
                            ];
65
                        } elseif ($type === GetAction::TYPE_FILES) {
66
                            $size = self::getFileSize($path);
67
                            $list[] = [
68
                                'title' => $file,
69
                                'name' => $file,
70
                                'link' => $url,
71
                                'size' => $size
72
                            ];
73
                        } else {
74
                            $list[] = $path;
75
                        }
76
                    } else {
77
                        $list[] = $path;
78
                    }
79
                } elseif (!isset($options['recursive']) || $options['recursive']) {
80
                    $list = array_merge($list, static::findFiles($path, $options, $type));
81
                }
82
            }
83
        }
84
        closedir($handle);
85
86
        return $list;
87
    }
88
89
    /**
90
     * @param string $path
91
     *
92
     * @return string filesize in(B|KB|MB|GB)
93
     */
94
    protected static function getFileSize($path)
95
    {
96
        $size = filesize($path);
97
        $labels = ['B', 'KB', 'MB', 'GB'];
98
        $factor = floor((strlen($size) - 1) / 3);
99
100
        return sprintf("%.1f ", $size / pow(1024, $factor)) . $labels[$factor];
101
    }
102
103
    /**
104
     * @inheritdoc
105
     *
106
     * @codeCoverageIgnore
107
     */
108
    private static function parseExcludePattern($pattern)
0 ignored issues
show
Bug introduced by
Consider using a different method name as you override a private method of the parent class.

Overwriting private methods is generally fine as long as you also use private visibility. It might still be preferable for understandability to use a different method name.

Loading history...
109
    {
110
        if (!is_string($pattern)) {
111
            throw new InvalidParamException('Exclude/include pattern must be a string.');
112
        }
113
        $result = [
114
            'pattern' => $pattern,
115
            'flags' => 0,
116
            'firstWildcard' => false,
117
        ];
118
        if (!isset($pattern[0])) {
119
            return $result;
120
        }
121
122
        if ($pattern[0] == '!') {
123
            $result['flags'] |= self::PATTERN_NEGATIVE;
124
            $pattern = StringHelper::byteSubstr($pattern, 1, StringHelper::byteLength($pattern));
125
        }
126
        $len = StringHelper::byteLength($pattern);
127
        if ($len && StringHelper::byteSubstr($pattern, -1, 1) == '/') {
128
            $pattern = StringHelper::byteSubstr($pattern, 0, -1);
129
            $len--;
130
            $result['flags'] |= self::PATTERN_MUSTBEDIR;
131
        }
132
        if (strpos($pattern, '/') === false) {
133
            $result['flags'] |= self::PATTERN_NODIR;
134
        }
135
        $result['firstWildcard'] = self::firstWildcardInPattern($pattern);
136
        if ($pattern[0] == '*' && self::firstWildcardInPattern(StringHelper::byteSubstr($pattern, 1, StringHelper::byteLength($pattern))) === false) {
137
            $result['flags'] |= self::PATTERN_ENDSWITH;
138
        }
139
        $result['pattern'] = $pattern;
140
141
        return $result;
142
    }
143
144
    /**
145
     * @inheritdoc
146
     *
147
     * @codeCoverageIgnore
148
     */
149
    private static function firstWildcardInPattern($pattern)
0 ignored issues
show
Bug introduced by
Consider using a different method name as you override a private method of the parent class.

Overwriting private methods is generally fine as long as you also use private visibility. It might still be preferable for understandability to use a different method name.

Loading history...
150
    {
151
        $wildcards = ['*', '?', '[', '\\'];
152
        $wildcardSearch = function ($r, $c) use ($pattern) {
153
            $p = strpos($pattern, $c);
154
155
            return $r === false ? $p : ($p === false ? $r : min($r, $p));
156
        };
157
158
        return array_reduce($wildcards, $wildcardSearch, false);
159
    }
160
161
    /**
162
     * @inheritdoc
163
     *
164
     * @codeCoverageIgnore
165
     */
166
    private static function normalizeOptions(array $options)
0 ignored issues
show
Bug introduced by
Consider using a different method name as you override a private method of the parent class.

Overwriting private methods is generally fine as long as you also use private visibility. It might still be preferable for understandability to use a different method name.

Loading history...
167
    {
168
        if (!array_key_exists('caseSensitive', $options)) {
169
            $options['caseSensitive'] = true;
170
        }
171
        if (isset($options['except'])) {
172
            foreach ($options['except'] as $key => $value) {
173
                if (is_string($value)) {
174
                    $options['except'][$key] = self::parseExcludePattern($value, $options['caseSensitive']);
0 ignored issues
show
Unused Code introduced by
The call to FileHelper::parseExcludePattern() has too many arguments starting with $options['caseSensitive'].

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
175
                }
176
            }
177
        }
178
        if (isset($options['only'])) {
179
            foreach ($options['only'] as $key => $value) {
180
                if (is_string($value)) {
181
                    $options['only'][$key] = self::parseExcludePattern($value, $options['caseSensitive']);
0 ignored issues
show
Unused Code introduced by
The call to FileHelper::parseExcludePattern() has too many arguments starting with $options['caseSensitive'].

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
182
                }
183
            }
184
        }
185
        return $options;
186
    }
187
}
188