FilesManagement   F
last analyzed

Complexity

Total Complexity 64

Size/Duplication

Total Lines 259
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 94
c 2
b 0
f 0
dl 0
loc 259
rs 3.28
wmc 64

8 Methods

Rating   Name   Duplication   Size   Complexity  
A createFolder() 0 12 6
B rrmdir() 0 31 9
A copyFile() 0 3 1
B deleteDirectory() 0 34 9
B recurseCopy() 0 16 7
B xcopy() 0 33 10
B rcopy() 0 28 11
B rmove() 0 31 11

How to fix   Complexity   

Complex Class

Complex classes like FilesManagement 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.

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 FilesManagement, and based on these observations, apply Extract Interface, too.

1
<?php declare(strict_types=1);
2
3
namespace XoopsModules\Publisher\Common;
4
5
/*
6
 You may not change or alter any portion of this comment or credits
7
 of supporting developers from this source code or any supporting source code
8
 which is considered copyrighted (c) material of the original comment or credit authors.
9
10
 This program is distributed in the hope that it will be useful,
11
 but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
 */
14
15
/**
16
 * @copyright   XOOPS Project (https://xoops.org)
17
 * @license     https://www.fsf.org/copyleft/gpl.html GNU public license
18
 * @author      mamba <[email protected]>
19
 */
20
trait FilesManagement
21
{
22
    /**
23
     * Function responsible for checking if a directory exists, we can also write in and create an index.html file
24
     *
25
     * @param string $folder The full path of the directory to check
26
     *
27
     * @throws \RuntimeException
28
     */
29
    public static function createFolder($folder): void
30
    {
31
        try {
32
            if (!\is_dir($folder)) {
33
                if (!\is_dir($folder) && !\mkdir($folder) && !\is_dir($folder)) {
34
                    throw new \RuntimeException(\sprintf('Unable to create the %s directory', $folder));
35
                }
36
37
                file_put_contents($folder . '/index.html', '<script>history.go(-1);</script>');
38
            }
39
        } catch (\Throwable $e) {
40
            echo 'Caught exception: ', $e->getMessage(), '<br>';
41
        }
42
    }
43
44
    public static function copyFile(string $file, string $folder): bool
45
    {
46
        return \copy($file, $folder);
47
    }
48
49
    public static function recurseCopy(string $src, string $dst): void
50
    {
51
        $dir = \opendir($src);
52
        if (!\mkdir($dst) && !\is_dir($dst)) {
53
            throw new \RuntimeException(\sprintf('Directory "%s" was not created', $dst));
54
        }
55
        while (false !== ($file = \readdir($dir))) {
56
            if (('.' !== $file) && ('..' !== $file)) {
57
                if (\is_dir($src . '/' . $file)) {
58
                    self::recurseCopy($src . '/' . $file, $dst . '/' . $file);
59
                } else {
60
                    \copy($src . '/' . $file, $dst . '/' . $file);
61
                }
62
            }
63
        }
64
        \closedir($dir);
65
    }
66
67
    /**
68
     * Copy a file, or recursively copy a folder and its contents
69
     * @param string $source Source path
70
     * @param string $dest   Destination path
71
     * @return bool Returns true on success, false on failure
72
     * @author      Aidan Lister <[email protected]>
73
     * @version     1.0.1
74
     * @link        https://aidanlister.com/2004/04/recursively-copying-directories-in-php/
75
     */
76
    public static function xcopy($source, $dest)
77
    {
78
        // Check for symlinks
79
        if (\is_link($source)) {
80
            return \symlink(\readlink($source), $dest);
81
        }
82
83
        // Simple copy for a file
84
        if (\is_file($source)) {
85
            return \copy($source, $dest);
86
        }
87
88
        // Make destination directory
89
        if (!\is_dir($dest) && !\mkdir($dest) && !\is_dir($dest)) {
90
            throw new \RuntimeException(\sprintf('Directory "%s" was not created', $dest));
91
        }
92
93
        // Loop through the folder
94
        $dir = \dir($source);
95
        if (false !== $dir) {
96
            while (false !== ($entry = $dir->read())) {
97
                // Skip pointers
98
                if ('.' === $entry || '..' === $entry) {
99
                    continue;
100
                }
101
                // Deep copy directories
102
                self::xcopy("$source/$entry", "$dest/$entry");
103
            }
104
            // Clean up
105
            $dir->close();
106
        }
107
108
        return true;
109
    }
110
111
    /**
112
     * Remove files and (sub)directories
113
     *
114
     * @param string $src source directory to delete
115
     *
116
     * @return bool true on success
117
     * @uses \Xmf\Module\Helper::isUserAdmin()
118
     *
119
     * @uses \Xmf\Module\Helper::getHelper()
120
     */
121
    public static function deleteDirectory($src)
122
    {
123
        // Only continue if user is a 'global' Admin
124
        if (!($GLOBALS['xoopsUser'] instanceof \XoopsUser) || !$GLOBALS['xoopsUser']->isAdmin()) {
125
            return false;
126
        }
127
128
        $success = true;
129
        // remove old files
130
        $dirInfo = new \SplFileInfo($src);
131
        // validate is a directory
132
        if ($dirInfo->isDir()) {
133
            $fileList = \array_diff(\scandir($src, \SCANDIR_SORT_NONE), ['..', '.']);
134
            foreach ($fileList as $k => $v) {
135
                $fileInfo = new \SplFileInfo("{$src}/{$v}");
136
                if ($fileInfo->isDir()) {
137
                    // recursively handle subdirectories
138
                    if (!$success = self::deleteDirectory($fileInfo->getRealPath())) {
139
                        break;
140
                    }
141
                } elseif (!($success = \unlink($fileInfo->getRealPath()))) {
142
                    break;
143
                }
144
            }
145
            // now delete this (sub)directory if all the files are gone
146
            if ($success) {
147
                $success = \rmdir($dirInfo->getRealPath());
148
            }
149
        } else {
150
            // input is not a valid directory
151
            $success = false;
152
        }
153
154
        return $success;
155
    }
156
157
    /**
158
     * Recursively remove directory
159
     *
160
     * @todo currently won't remove directories with hidden files, should it?
161
     *
162
     * @param string $src directory to remove (delete)
163
     *
164
     * @return bool true on success
165
     */
166
    public static function rrmdir($src)
167
    {
168
        // Only continue if user is a 'global' Admin
169
        if (!($GLOBALS['xoopsUser'] instanceof \XoopsUser) || !$GLOBALS['xoopsUser']->isAdmin()) {
170
            return false;
171
        }
172
173
        // If source is not a directory stop processing
174
        if (!\is_dir($src)) {
175
            return false;
176
        }
177
178
        $success = true;
0 ignored issues
show
Unused Code introduced by
The assignment to $success is dead and can be removed.
Loading history...
179
180
        // Open the source directory to read in files
181
        $iterator = new \DirectoryIterator($src);
182
        foreach ($iterator as $fObj) {
183
            if ($fObj->isFile()) {
184
                $filename = $fObj->getPathname();
185
                $fObj     = null; // clear this iterator object to close the file
0 ignored issues
show
Unused Code introduced by
The assignment to $fObj is dead and can be removed.
Loading history...
186
                if (!\unlink($filename)) {
187
                    return false; // couldn't delete the file
188
                }
189
            } elseif (!$fObj->isDot() && $fObj->isDir()) {
190
                // Try recursively on directory
191
                self::rrmdir($fObj->getPathname());
192
            }
193
        }
194
        $iterator = null;   // clear iterator Obj to close file/directory
0 ignored issues
show
Unused Code introduced by
The assignment to $iterator is dead and can be removed.
Loading history...
195
196
        return \rmdir($src); // remove the directory & return results
197
    }
198
199
    /**
200
     * Recursively move files from one directory to another
201
     *
202
     * @param string $src  - Source of files being moved
203
     * @param string $dest - Destination of files being moved
204
     *
205
     * @return bool true on success
206
     */
207
    public static function rmove($src, $dest)
208
    {
209
        // Only continue if user is a 'global' Admin
210
        if (!($GLOBALS['xoopsUser'] instanceof \XoopsUser) || !$GLOBALS['xoopsUser']->isAdmin()) {
211
            return false;
212
        }
213
214
        // If source is not a directory stop processing
215
        if (!\is_dir($src)) {
216
            return false;
217
        }
218
219
        // If the destination directory does not exist and could not be created stop processing
220
        if (!\is_dir($dest) && !\mkdir($dest) && !\is_dir($dest)) {
221
            return false;
222
        }
223
224
        // Open the source directory to read in files
225
        $iterator = new \DirectoryIterator($src);
226
        foreach ($iterator as $fObj) {
227
            if ($fObj->isFile()) {
228
                \rename($fObj->getPathname(), "{$dest}/" . $fObj->getFilename());
229
            } elseif (!$fObj->isDot() && $fObj->isDir()) {
230
                // Try recursively on directory
231
                self::rmove($fObj->getPathname(), "{$dest}/" . $fObj->getFilename());
232
                //                rmdir($fObj->getPath()); // now delete the directory
233
            }
234
        }
235
        $iterator = null;   // clear iterator Obj to close file/directory
0 ignored issues
show
Unused Code introduced by
The assignment to $iterator is dead and can be removed.
Loading history...
236
237
        return \rmdir($src); // remove the directory & return results
238
    }
239
240
    /**
241
     * Recursively copy directories and files from one directory to another
242
     *
243
     * @param string $src  - Source of files being moved
244
     * @param string $dest - Destination of files being moved
245
     *
246
     * @return bool true on success
247
     * @uses \Xmf\Module\Helper::isUserAdmin()
248
     *
249
     * @uses \Xmf\Module\Helper::getHelper()
250
     */
251
    public static function rcopy($src, $dest)
252
    {
253
        // Only continue if user is a 'global' Admin
254
        if (!($GLOBALS['xoopsUser'] instanceof \XoopsUser) || !$GLOBALS['xoopsUser']->isAdmin()) {
255
            return false;
256
        }
257
258
        // If source is not a directory stop processing
259
        if (!\is_dir($src)) {
260
            return false;
261
        }
262
263
        // If the destination directory does not exist and could not be created stop processing
264
        if (!\is_dir($dest) && !\mkdir($dest) && !\is_dir($dest)) {
265
            return false;
266
        }
267
268
        // Open the source directory to read in files
269
        $iterator = new \DirectoryIterator($src);
270
        foreach ($iterator as $fObj) {
271
            if ($fObj->isFile()) {
272
                \copy($fObj->getPathname(), "{$dest}/" . $fObj->getFilename());
273
            } elseif (!$fObj->isDot() && $fObj->isDir()) {
274
                self::rcopy($fObj->getPathname(), "{$dest}/" . $fObj->getFilename());
275
            }
276
        }
277
278
        return true;
279
    }
280
}
281