Passed
Pull Request — master (#1283)
by Diego
07:40
created

CommandHelper   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 273
Duplicated Lines 0 %

Test Coverage

Coverage 97.22%

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 66
c 3
b 0
f 0
dl 0
loc 273
ccs 70
cts 72
cp 0.9722
rs 9.76
wmc 33

9 Methods

Rating   Name   Duplication   Size   Complexity  
B compareDirectories() 0 47 7
A shouldCopyItem() 0 15 4
A compareFiles() 0 7 3
A getViewPath() 0 9 2
A shouldCompareItem() 0 12 3
A copyDirectory() 0 47 6
A getStubPath() 0 7 2
A getPackagePath() 0 7 2
A isIgnoredItem() 0 13 4
1
<?php
2
3
namespace JeroenNoten\LaravelAdminLte\Helpers;
4
5
use Illuminate\Support\Facades\File;
6
use Illuminate\Support\Str;
7
8
class CommandHelper
9
{
10
    /**
11
     * The path to the package's root folder.
12
     *
13
     * @var string
14
     */
15
    protected static $packagePath = __DIR__.'/../../';
16
17
    /**
18
     * The path to the package's stubs folder.
19
     *
20
     * @var string
21
     */
22
    protected static $stubsPath = __DIR__.'/../Console/stubs';
23
24
    /**
25
     * Copies a directory to the specified destination. Returns whether the
26
     * directory could be copied successfully.
27
     *
28
     * @param  string  $directory  The path of the directory to be copied
29
     * @param  string  $destination  The path of the destination folder
30
     * @param  bool  $force  Whether to force the overwrite of existing files
31
     * @param  bool  $recursive  Whether to copy subfolders recursively
32
     * @param  array  $ignores  An array of name patterns to ignore while copying
33
     * @return bool
34
     */
35 28
    public static function copyDirectory(
36
        $directory,
37
        $destination,
38
        $force = false,
39
        $recursive = false,
40
        $ignores = []
41
    ) {
42
        // Check if we can open the source folder.
43
44 28
        if (! is_resource($dirHandler = @opendir($directory))) {
45 2
            return false;
46
        }
47
48
        // Ensure the destination folder exists.
49
50 26
        File::ensureDirectoryExists($destination);
51
52
        // Copy the folder to the destination. Note we will skip dots items.
53
54 26
        $avoids = array_merge($ignores, ['.', '..']);
55
56 26
        while (($item = readdir($dirHandler)) !== false) {
57 26
            $s = $directory.DIRECTORY_SEPARATOR.$item;
58 26
            $t = $destination.DIRECTORY_SEPARATOR.$item;
59
60
            // Check if this item should be copied or ignored.
61
62 26
            if (! self::shouldCopyItem($s, $t, $force, $recursive, $avoids)) {
63 26
                continue;
64
            }
65
66
            // Finally, copy the file/folder to destination. If the item is a
67
            // folder we proceed recursively. Otherwise, copy the file to the
68
            // destination.
69
70 26
            $res = File::isDirectory($s)
71 21
                ? self::copyDirectory($s, $t, $force, $recursive, $ignores)
72 26
                : File::copy($s, $t);
73
74 26
            if (! $res) {
75
                closedir($dirHandler);
76
                return false;
77
            }
78
        }
79
80 26
        closedir($dirHandler);
81 26
        return true;
82
    }
83
84
    /**
85
     * Compares two directories file by file. Returns a boolean indicating
86
     * whether the two directories are equal, or null when one of the
87
     * directories does not exists.
88
     *
89
     * @param  string  $dir1  The path of the first folder
90
     * @param  string  $dir2  The path of the second folder
91
     * @param  bool  $recursive  Whether to compare subfolders recursively
92
     * @param  array  $ignores  An array of name patterns to ignore while comparing
93
     * @return bool|null
94
     */
95 25
    public static function compareDirectories(
96
        $dir1,
97
        $dir2,
98
        $recursive = false,
99
        $ignores = []
100
    ) {
101
        // Check if we can open the first folder.
102
103 25
        if (! is_resource($dirHandler = @opendir($dir1))) {
104 1
            return;
105
        }
106
107
        // Check if the second folder exists.
108
109 25
        if (! is_dir($dir2)) {
110 12
            return;
111
        }
112
113
        // Now, compare the folders. Note we will skip dots items.
114
115 24
        $avoids = array_merge($ignores, ['.', '..']);
116
117 24
        while (($item = readdir($dirHandler)) !== false) {
118 24
            $s = $dir1.DIRECTORY_SEPARATOR.$item;
119 24
            $t = $dir2.DIRECTORY_SEPARATOR.$item;
120
121
            // Check if this item should be compared or ignored.
122
123 24
            if (! self::shouldCompareItem($s, $recursive, $avoids)) {
124 23
                continue;
125
            }
126
127
            // Finally, compare the files/folders. If the item to compare is a
128
            // folder we proceed recursively.
129
130 24
            $res = File::isDirectory($s)
131 20
                ? (bool) self::compareDirectories($s, $t, $recursive, $ignores)
132 23
                : self::compareFiles($s, $t);
133
134 24
            if (! $res) {
135 7
                closedir($dirHandler);
136 7
                return false;
137
            }
138
        }
139
140 22
        closedir($dirHandler);
141 22
        return true;
142
    }
143
144
    /**
145
     * Checks if two files are equals by comparing their hash values.
146
     *
147
     * @param  string  $file1  The path to the first file
148
     * @param  string  $file2  The path to the second file
149
     * @return bool
150
     */
151 23
    public static function compareFiles($file1, $file2)
152
    {
153 23
        if (! File::isFile($file1) || ! File::isFile($file2)) {
154 6
            return false;
155
        }
156
157 23
        return File::hash($file1) === File::hash($file2);
158
    }
159
160
    /**
161
     * Gets the fully qualified path to the specified package resource.
162
     *
163
     * @param  string  $path  Relative path to the resource
164
     * @return string
165
     */
166 24
    public static function getPackagePath($path = null)
167
    {
168 24
        if (empty($path)) {
169 1
            return self::$packagePath;
170
        }
171
172 24
        return self::$packagePath.DIRECTORY_SEPARATOR.$path;
173
    }
174
175
    /**
176
     * Gets the fully qualified path to the specified package stub resource.
177
     *
178
     * @param  string  $path  Relative path to the stub resource
179
     * @return string
180
     */
181 24
    public static function getStubPath($path = null)
182
    {
183 24
        if (empty($path)) {
184 1
            return self::$stubsPath;
185
        }
186
187 24
        return self::$stubsPath.DIRECTORY_SEPARATOR.$path;
188
    }
189
190
    /**
191
     * Gets the fully qualified path to the specified view resource, relative to
192
     * the configured view path.
193
     *
194
     * @param  string  $path  Relative path to some view resource
195
     * @return string
196
     */
197 24
    public static function getViewPath($path = null)
198
    {
199 24
        $basePath = config('view.paths')[0] ?? resource_path('views');
200
201 24
        if (empty($path)) {
202 24
            return $basePath;
203
        }
204
205 24
        return $basePath.DIRECTORY_SEPARATOR.$path;
206
    }
207
208
    /**
209
     * Checks whether an item (file or folder) should be copied to the
210
     * specified destination by analyzing the recursive and force flags, and a
211
     * set of item name patterns to be ignored.
212
     *
213
     * @param  string  $s  The source item path
214
     * @param  string  $t  The target destination path
215
     * @param  bool  $fFlag  The value of the force flag
216
     * @param  bool  $rFlag  The value of the recursive flag
217
     * @param  array  $ignores  An array of name patterns to be ignored
218
     * @return bool
219
     */
220 26
    protected static function shouldCopyItem($s, $t, $fFlag, $rFlag, $ignores)
221
    {
222
        // At first, we should copy the item when it's a directoy and the
223
        // recursive flag is set, or when it's a file and the target path does
224
        // not exists or the force flag is set.
225
226 26
        $shouldCopy = File::isDirectory($s)
227 26
            ? $rFlag
228 26
            : (! File::exists($t) || $fFlag);
229
230
        // Then we should also check the item name does not match any of the
231
        // ignore patterns.
232
233 26
        return $shouldCopy
234 26
            && ! self::isIgnoredItem(File::basename($s), $ignores);
235
    }
236
237
    /**
238
     * Checks whether an item (file or folder) should be compared by analyzing
239
     * the recursive flag, and a set of item name patterns to be ignored.
240
     *
241
     * @param  string  $s  The source item path
242
     * @param  bool  $rFlag  The value of the recursive flag
243
     * @param  array  $ignores  An array of name patterns to be ignored
244
     * @return bool
245
     */
246 24
    protected static function shouldCompareItem($s, $rFlag, $ignores)
247
    {
248
        // At first, we should compare the item when it's a file or when it's
249
        // a directory and the recursive flag is set.
250
251 24
        $shouldCompare = File::isFile($s) || $rFlag;
252
253
        // Then we should also check that the item name does not match any of
254
        // the ignore patterns.
255
256 24
        return $shouldCompare
257 24
            && ! self::isIgnoredItem(File::basename($s), $ignores);
258
    }
259
260
    /**
261
     * Checks if the name of a folder or file belongs to a set of specified
262
     * patterns to be ignored.
263
     *
264
     * @param  string  $name  The name of the folder or file to verify
265
     * @param  array  $ignores  An array of name patterns to be ignored
266
     * @return bool
267
     */
268 31
    protected static function isIgnoredItem($name, $ignores)
269
    {
270 31
        foreach ($ignores as $pattern) {
271 31
            $match = Str::startsWith($pattern, 'regex:')
272 2
                ? preg_match(Str::substr($pattern, 6), $name)
273 31
                : Str::is($pattern, $name);
274
275 31
            if ($match) {
276 29
                return true;
277
            }
278
        }
279
280 31
        return false;
281
    }
282
}
283