HackedFileGroup::scanDirectory()   C
last analyzed

Complexity

Conditions 11
Paths 4

Size

Total Lines 52
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
eloc 38
nc 4
nop 8
dl 0
loc 52
rs 5.9999
c 0
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
namespace Cerbere\Model\Hacked;
4
5
/**
6
 * Represents a group of files on the local filesystem.
7
 */
8
class HackedFileGroup
9
{
10
    /**
11
     * @var string
12
     */
13
    protected $base_path = '';
14
15
    /**
16
     * @var array
17
     */
18
    protected $files = array();
19
20
    /**
21
     * @var array
22
     */
23
    protected $files_hashes = array();
24
25
    /**
26
     * @var array
27
     */
28
    protected $file_mtimes = array();
29
30
    /**
31
     * @var HackedFileHasher
32
     */
33
    protected $hasher;
34
35
    /**
36
     * Constructor.
37
     *
38
     * @param string $base_path
39
     * @param HackedFileHasher $hasher
40
     */
41
    public function __construct($base_path, HackedFileHasher $hasher = null)
42
    {
43
        if (null === $hasher) {
44
            $hasher = new HackedFileIgnoreEndingsHasher();
45
        }
46
47
        $this->base_path = $base_path;
48
        $this->hasher = $hasher;
49
    }
50
51
    /**
52
     * Hash all files listed in the file group.
53
     */
54
    public function computeHashes()
55
    {
56
        foreach ($this->files as $filename) {
57
            $this->files_hashes[$filename] = $this->hasher->hash($this->base_path . DIRECTORY_SEPARATOR . $filename);
58
        }
59
    }
60
61
    /**
62
     * Determine if a file exists.
63
     * @param string $file
64
     * @return bool
65
     */
66
    public function fileExists($file)
67
    {
68
        return file_exists($this->base_path . DIRECTORY_SEPARATOR . $file);
69
    }
70
71
    /**
72
     * Return a new hackedFileGroup listing all files inside the given $path.
73
     *
74
     * @param string $path
75
     *
76
     * @return HackedFileGroup
77
     */
78
    public static function createFromDirectory($path)
79
    {
80
        $filegroup = new self($path);
81
        // Find all the files in the path, and add them to the file group.
82
        $filegroup->scanBasePath();
83
84
        return $filegroup;
85
    }
86
87
    /**
88
     * Locate all sensible files at the base path of the file group.
89
     */
90
    public function scanBasePath()
91
    {
92
        $white_list = array('.', '..', 'CVS', '.svn', '.git',);
93
        $files = self::scanDirectory($this->base_path, '/.*/', $white_list);
94
95
        foreach ($files as $file) {
96
            $filename = str_replace($this->base_path . DIRECTORY_SEPARATOR, '', $file->filename);
97
            $this->files[] = $filename;
98
        }
99
    }
100
101
    /**
102
     * @param string $dir
103
     * @param int $mask
104
     * @param array $nomask
105
     * @param callable $callback
106
     * @param bool|true $recurse
107
     * @param string $key
108
     * @param int $min_depth
109
     * @param int $depth
110
     *
111
     * @return array
112
     */
113
    public static function scanDirectory(
114
      $dir,
115
      $mask,
116
      $nomask = array('.', '..', 'CVS'),
117
      $callback = null,
118
      $recurse = true,
119
      $key = 'filename',
120
      $min_depth = 0,
121
      $depth = 0
122
    ) {
123
        $key = (in_array($key, array('filename', 'basename', 'name')) ? $key : 'filename');
124
        $files = array();
125
126
        if (is_dir($dir) && $handle = opendir($dir)) {
127
            while (false !== ($file = readdir($handle))) {
128
                if (!in_array($file, $nomask)) {
129
                    if (is_dir($dir . DIRECTORY_SEPARATOR . $file) && $recurse) {
130
                        // Give priority to files in this folder by merging them in after any subdirectory files.
131
                        $files = array_merge(
132
                          self::scanDirectory(
133
                            $dir . DIRECTORY_SEPARATOR . $file,
134
                            $mask,
135
                            $nomask,
136
                            $callback,
137
                            $recurse,
138
                            $key,
139
                            $min_depth,
140
                            $depth + 1
141
                          ),
142
                          $files
143
                        );
144
                    } elseif ($depth >= $min_depth && preg_match($mask, $file)) {
145
                        // Always use this match over anything already set in $files with the same $$key.
146
                        $filename = $dir . DIRECTORY_SEPARATOR . $file;
147
                        $basename = basename($file);
148
                        $name = substr($basename, 0, strrpos($basename, '.'));
149
                        $files[$$key] = new \stdClass();
150
                        $files[$$key]->filename = $filename;
151
                        $files[$$key]->basename = $basename;
152
                        $files[$$key]->name = $name;
153
                        if (is_callable($callback)) {
154
                            $callback($filename);
155
                        }
156
                    }
157
                }
158
            }
159
160
            closedir($handle);
161
        }
162
163
        return $files;
164
    }
165
166
    /**
167
     * Return a new hackedFileGroup listing all files specified.
168
     *
169
     * @param string $path
170
     * @param array $files
171
     *
172
     * @return HackedFileGroup
173
     */
174
    public static function createFromList($path, array $files)
175
    {
176
        $filegroup = new self($path);
177
        // Find all the files in the path, and add them to the file group.
178
        $filegroup->files = $files;
179
180
        return $filegroup;
181
    }
182
183
    /**
184
     * @param string $file
185
     *
186
     * @return string|bool
187
     */
188
    public function getFileHash($file)
189
    {
190
        if (isset($this->files_hashes[$file])) {
191
            return $this->files_hashes[$file];
192
        }
193
194
        return false;
195
    }
196
197
    /**
198
     * @param string $file
199
     * @return string
200
     */
201
    public function getFileLocation($file)
202
    {
203
        return $this->base_path . DIRECTORY_SEPARATOR . $file;
204
    }
205
206
    /**
207
     * @return array
208
     */
209
    public function getFiles()
210
    {
211
        return $this->files;
212
    }
213
214
    /**
215
     * Determine if the given file is binary.
216
     * @param string $file
217
     * @return bool
218
     */
219
    public function isNotBinary($file)
220
    {
221
        return is_readable($this->base_path . DIRECTORY_SEPARATOR . $file)
222
        && !self::isBinary($this->base_path . DIRECTORY_SEPARATOR . $file);
223
    }
224
225
    /**
226
     * Determine if a file is a binary file.
227
     *
228
     * Taken from: http://www.ultrashock.com/forums/server-side/checking-if-a-file-is-binary-98391.html
229
     * and then tweaked in: http://drupal.org/node/760362.
230
     *
231
     * @param string $file
232
     *
233
     * @return bool
234
     */
235
    public static function isBinary($file)
236
    {
237
        if (file_exists($file)) {
238
            if (!is_file($file)) {
239
                return false;
240
            }
241
            if (!is_readable($file)) {
242
                return true;
243
            }
244
245
            $fh = fopen($file, "r");
246
            $blk = fread($fh, 512);
247
            fclose($fh);
248
            clearstatcache();
249
250
            return (substr_count($blk, "^\r\n") / 512 > 0.3
251
              || substr_count($blk, "^ -~") / 512 > 0.3
252
              || substr_count($blk, "\x00") > 0);
253
        }
254
255
        return false;
256
    }
257
258
    /**
259
     * Determine if the given file is readable.
260
     * @param string $file
261
     * @return bool
262
     */
263
    public function isReadable($file)
264
    {
265
        return is_readable($this->base_path . DIRECTORY_SEPARATOR . $file);
266
    }
267
}
268