CommandHelper   A
last analyzed

Complexity

Total Complexity 33

Size/Duplication

Total Lines 277
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 66
c 1
b 0
f 0
dl 0
loc 277
ccs 72
cts 72
cp 1
rs 9.76
wmc 33

9 Methods

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